<commit_before>/*
  termap - Terminal Map Viewer
  by <NAME> <<EMAIL>>

  The Console Vector Tile renderer - bäm!
*/
'use strict';
const Promise = require('bluebird');
const x256 = require('x256');
const simplify = require('simplify-js');

const Canvas = require('./Canvas');
const LabelBuffer = require('./LabelBuffer');
const Styler = require('./Styler');
const utils = require('./utils');
const config = require('./config');

class Renderer {
  constructor(output, tileSource) {
    this.output = output;
    this.tileSource = tileSource;
    this.labelBuffer = new LabelBuffer();
  }

  loadStyleFile(file) {
    this.styler = new Styler(file);
    this.tileSource.useStyler(this.styler);
  }

  setSize(width, height) {
    this.width = width;
    this.height = height;
    this.canvas = new Canvas(width, height);
  }

  draw(center, zoom) {
    if (this.isDrawing) return Promise.reject();
    this.isDrawing = true;

    this.labelBuffer.clear();
    this._seen = {};

    let ref;
    const color = ((ref = this.styler.styleById['background']) !== null ?
      ref.paint['background-color']
      :
      void 0
    );
    if (color) {
      this.canvas.setBackground(x256(utils.hex2rgb(color)));
    }

    this.canvas.clear();

    return Promise.resolve(this._visibleTiles(center, zoom)).map((tile) => {
      return this._getTile(tile);
    }).map((tile) => {
      return this._getTileFeatures(tile, zoom);
    }).then((tiles) => {
      this._renderTiles(tiles);
    }).then(() => {
      return this._getFrame();
    }).catch((e) => {
      return console.log(e);
    }).finally((frame) => {
      this.isDrawing = false;
      this.lastDrawAt = Date.now();
      return frame;
    });
  }

  _visibleTiles(center, zoom) {
    const z = utils.baseZoom(zoom);
    center = utils.ll2tile(center.lon, center.lat, z);
    
    const tiles = [];
    const tileSize = utils.tilesizeAtZoom(zoom);
    
    for (let y = Math.floor(center.y) - 1; y <= Math.floor(center.y) + 1; y++) {
      for (let x = Math.floor(center.x) - 1; x <= Math.floor(center.x) + 1; x++) {
        const tile = {x, y, z};
        const position = {
          x: this.width / 2 - (center.x - tile.x) * tileSize,
          y: this.height / 2 - (center.y - tile.y) * tileSize,
        };
        
        const gridSize = Math.pow(2, z);
        
        tile.x %= gridSize;
        
        if (tile.x < 0) {
          tile.x = z === 0 ? 0 : tile.x + gridSize;
        }
        
        if (tile.y < 0 || tile.y >= gridSize || position.x + tileSize < 0 || position.y + tileSize < 0 || position.x > this.width || position.y > this.height) {
          continue;
        }
        
        tiles.push({
          xyz: tile,
          zoom,
          position,
          size: tileSize,
        });
      }
    }
    return tiles;
  }

  _getTile(tile) {
    return this.tileSource
      .getTile(tile.xyz.z, tile.xyz.x, tile.xyz.y)
      .then((data) => {
        tile.data = data;
        return tile;
      });
  }

  _getTileFeatures(tile, zoom) {
    const position = tile.position;
    const layers = {};
    const drawOrder = this._generateDrawOrder(zoom);
    for (const layerId of drawOrder) {
      const layer = (tile.data.layers || {})[layerId];
      if (!layer) {
        continue;
      }
      
      const scale = layer.extent / utils.tilesizeAtZoom(zoom);
      layers[layerId] = {
        scale: scale,
        features: layer.tree.search({
          minX: -position.x * scale,
          minY: -position.y * scale,
          maxX: (this.width - position.x) * scale,
          maxY: (this.height - position.y) * scale
        }),
      };
    }
    tile.layers = layers;
    return tile;
  }

  _renderTiles(tiles) {
    const labels = [];
    
    const drawOrder = this._generateDrawOrder(tiles[0].xyz.z);
    for (const layerId in drawOrder) {
      for (const tile in tiles) {
        const layer = tile.layers[layerId];
        if (!layer) continue;
        for (const feature of layer.features) {
          // continue if feature.id and drawn[feature.id]
          // drawn[feature.id] = true;
          if (layerId.match(/label/)) {
            labels.push({
              tile,
              feature,
              scale: layer.scale
            });
          } else {<commit_msg>Fix breaking bug introduced in 0353effa67974e1189517da698ba7176fbcdf6d9<commit_after>/*
  termap - Terminal Map Viewer
  by <NAME> <<EMAIL>>

  The Console Vector Tile renderer - bäm!
*/
'use strict';
const Promise = require('bluebird');
const x256 = require('x256');
const simplify = require('simplify-js');

const Canvas = require('./Canvas');
const LabelBuffer = require('./LabelBuffer');
const Styler = require('./Styler');
const utils = require('./utils');
const config = require('./config');

class Renderer {
  constructor(output, tileSource) {
    this.output = output;
    this.tileSource = tileSource;
    this.labelBuffer = new LabelBuffer();
  }

  loadStyleFile(file) {
    this.styler = new Styler(file);
    this.tileSource.useStyler(this.styler);
  }

  setSize(width, height) {
    this.width = width;
    this.height = height;
    this.canvas = new Canvas(width, height);
  }

  draw(center, zoom) {
    if (this.isDrawing) return Promise.reject();
    this.isDrawing = true;

    this.labelBuffer.clear();
    this._seen = {};

    let ref;
    const color = ((ref = this.styler.styleById['background']) !== null ?
      ref.paint['background-color']
      :
      void 0
    );
    if (color) {
      this.canvas.setBackground(x256(utils.hex2rgb(color)));
    }

    this.canvas.clear();

    return Promise.resolve(this._visibleTiles(center, zoom)).map((tile) => {
      return this._getTile(tile);
    }).map((tile) => {
      return this._getTileFeatures(tile, zoom);
    }).then((tiles) => {
      this._renderTiles(tiles);
    }).then(() => {
      return this._getFrame();
    }).catch((e) => {
      return console.log(e);
    }).finally((frame) => {
      this.isDrawing = false;
      this.lastDrawAt = Date.now();
      return frame;
    });
  }

  _visibleTiles(center, zoom) {
    const z = utils.baseZoom(zoom);
    center = utils.ll2tile(center.lon, center.lat, z);
    
    const tiles = [];
    const tileSize = utils.tilesizeAtZoom(zoom);
    
    for (let y = Math.floor(center.y) - 1; y <= Math.floor(center.y) + 1; y++) {
      for (let x = Math.floor(center.x) - 1; x <= Math.floor(center.x) + 1; x++) {
        const tile = {x, y, z};
        const position = {
          x: this.width / 2 - (center.x - tile.x) * tileSize,
          y: this.height / 2 - (center.y - tile.y) * tileSize,
        };
        
        const gridSize = Math.pow(2, z);
        
        tile.x %= gridSize;
        
        if (tile.x < 0) {
          tile.x = z === 0 ? 0 : tile.x + gridSize;
        }
        
        if (tile.y < 0 || tile.y >= gridSize || position.x + tileSize < 0 || position.y + tileSize < 0 || position.x > this.width || position.y > this.height) {
          continue;
        }
        
        tiles.push({
          xyz: tile,
          zoom,
          position,
          size: tileSize,
        });
      }
    }
    return tiles;
  }

  _getTile(tile) {
    return this.tileSource
      .getTile(tile.xyz.z, tile.xyz.x, tile.xyz.y)
      .then((data) => {
        tile.data = data;
        return tile;
      });
  }

  _getTileFeatures(tile, zoom) {
    const position = tile.position;
    const layers = {};
    const drawOrder = this._generateDrawOrder(zoom);
    for (const layerId of drawOrder) {
      const layer = (tile.data.layers || {})[layerId];
      if (!layer) {
        continue;
      }
      
      const scale = layer.extent / utils.tilesizeAtZoom(zoom);
      layers[layerId] = {
        scale: scale,
        features: layer.tree.search({
          minX: -position.x * scale,
          minY: -position.y * scale,
          maxX: (this.width - position.x) * scale,
          maxY: (this.height - position.y) * scale
        }),
      };
    }
    tile.layers = layers;
    return tile;
  }

  _renderTiles(tiles) {
    const labels = [];
    
    const drawOrder = this._generateDrawOrder(tiles[0].xyz.z);
    for (const layerId of drawOrder) {
      for (const tile of tiles) {
        const layer = tile.layers[layerId];
        if (!layer) continue;
        for (const feature of layer.features) {
          // continue if feature.id and drawn[feature.id]
          // drawn[feature.id] = true;
          if (layerId.match(/label/)) {
            labels.push({
              tile,
              feature,
              scale: layer.scale
            });
          } else {
{'fraction_non_alphanumeric': 0.15086906141367323, 'fraction_numerical': 0.008922363847045192, 'mean_word_length': 2.0220588235294117, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1823829', 'n_tokens_mistral': 2846, 'n_tokens_neox': 2757, 'n_words': 619}