<commit_before>/*jshint esversion: 6 */ /*jslint single*/
console.clear();

// Firebase
var database = firebase.database();
var databaseEndpoint = '/beta/';

// GeoJSON objects
var geojson = featureCollection([]);
var FEATURE = null; // create empty feature

// FIPS are unique codes for a county
var FIPS = [];
var tags = [];
var filter;
var baseFilter = ['in', 'FIPS'];

var colorHighlightedCounty = "#888888";
var paletteColors = [
  '#ffffcc', '#a1dab4', '#41b6c4', '#2c7fb8', '#253494',
  '#fed976', '#feb24c', '#fd8d3c', '#f03b20', '#bd0026'
];

// Mapbox map
var map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v9',
  center: [-98, 38.88],
  minZoom: 2,
  zoom: 3
});

var overlay = document.getElementById('map-overlay');

// Create a popup, but don't add it to the map yet.
var popup = new mapboxgl.Popup({
  closeButton: false
});

map.on('load', function() {
  // Add the source to query. In this example we're using
  // county polygons uploaded as vector tiles
  map.addSource('counties', {
    "type": "vector",
    "url": "mapbox://mapbox.82pkq93d"
  });

  map.addLayer({
    "id": "counties",
    "type": "fill",
    "source": "counties",
    "source-layer": "original",
    "paint": {
      "fill-outline-color": "rgba(0,0,0,0.1)",
      "fill-color": "rgba(0,0,0,0.1)"
    }
  }, 'place-city-sm'); // Place polygon under these labels.

  paletteColors.forEach(function(color) {
    lay = addLayer(color);
    map.addLayer(lay, 'place-city-sm'); // Place polygon under these labels.)
  });

  // Border highlighted layer
  map.addLayer(addCountyBorderLayer(), 'place-city-sm');

  // Database
  var databaseObject = [];
  var rootRef = firebase.database().ref(databaseEndpoint);
  rootRef.once('value', function(snapshot) {

    if (snapshot.val() !== null) {
      databaseObject = snapshot.val();
      // the endpoint, or name of the object in the database is 'geojson/'
      //   so simplifiy the name by extracting the data by the name of 'geojson'
      geojson = databaseObject.geojson;

      if (geojson.features !== undefined) {
        setPaintColors(geojson);
      } else { // data base is NOT empty, but has no features
        geojson = featureCollection([]);
      }

    } else { // data base is empty
      geojson = featureCollection([]);
    }
  });

  map.on('click', function(e) {
    console.log('click');

    let queryFeature;
    // let checkbox = $('input[name="city-county-checkbox"]').bootstrapSwitch('state');
    checkbox = false; // TODO hardcode to false = County

    // Since we clicked on a new feature, nullify the previous one
    FEATURE = null;

    // Create a new GeoJson feature and properties
    let p = point([e.lngLat.lng, e.lngLat.lat]);
    FEATURE = feature(p);

    //
    if (checkbox === true) { // City
      queryFeature = map.queryRenderedFeatures(e.point);
      FEATURE.properties.name = queryFeature[0].properties.name;
    } else { // County
      queryFeature = map.queryRenderedFeatures(e.point, {
        layers: ['counties']
      });

      FEATURE.properties.FIPS = queryFeature[0].properties.FIPS;
      FEATURE.properties.name = queryFeature[0].properties.COUNTY;

      // add border when county is selected
      filter = baseFilter;
      filter = filter.concat(FEATURE.properties.FIPS);
      map.setFilter("county-border", filter);
    }

    // compare geojson for the current FIPS value, then extract the tags to update the UI
    indexOfFIPS = getFIPSByMap(geojson, FEATURE);
    if (indexOfFIPS != -1) {
      let t = geojson.features[indexOfFIPS].properties.tags;
      $("input[name='tags']").tagsinput('removeAll');
      $("input[name='tags']").tagsinput('add', t);
    }

    $(".county").html(FEATURE.properties.name);

  });

  map.on('mousemove', function(e) {
    var features = map.queryRenderedFeatures(e.point, {
      layers: ['counties']
    });

    // Change the cursor style as a UI indicator.
    map.getCanvas().style.cursor = features.length ? 'pointer' : '';

    // Remove things if no feature was found.
    if (!features.length) {
      popup.remove();
      // map.setFilter('counties-highlighted', ['in', 'COUNTY', '']);
      // overlay.style.display = 'none';
      return;
    }

    // Single out the first found feature on mouseove.
    var feature = features[0];

    // Query the counties layer visible in the map. Use the filter
    // param to only collect results that share the same county name.
    var relatedFeatures = map.querySourceFeatures('counties', {
      sourceLayer: 'original',
      filter: ['in', 'COUNTY', feature.properties.COUNTY]
    });

    // Display a popup with the name of the county
    popup.setLngLat(e.lngLat)
      .setText(feature.properties.COUNTY)
      .addTo(map);
  });
});

/////
function setPaintColors(geoJsonObject) {

  byColor = getFIPSByColor(geoJsonObject);

  // Special case when trying to remove the 'last' county
  if (byColor.length === 0) {
    filter = baseFilter;
    filter = filter.concat('[ ]');
    map.setFilter(layer, filter);
    return;
  }

  // Remove layers for each color to ensure UI is updated
  // Then replace each
  paletteColors.forEach(function(color) {
    rawCurrentColor = rawColorValue(color);
    layer = 'counties-highlighted-' + rawCurrentColor;
    map.removeLayer(layer);

    lay = addLayer(color);
    map.addLayer(lay, 'place-city-sm'); // Place polygon under these labels.)
  });

  byColor.forEach(function(colorRow) {
    color = colorRow.color;
    rawCurrentColor = rawColorValue(color);
    layer = 'counties-highlighted-' + rawCurrentColor;

    filter = baseFilter;
    filter = filter.concat(colorRow.FIPS);

    map.setFilter(layer, filter);
  });
}
/////

// GeoJson objects

// main geojson key
function featureCollection(f) {
  return {
    type: 'FeatureCollection',
    features: f
  };
}

// generate a geojson feature
function feature(geom) {
  return {
    type: 'Feature',
    geometry: geom,
    properties: properties()
  };
}

//  expects [longitude, latitude]
function point(coordinates) {
  return {
    type: 'Point',
    coordinates: coordinates
  };
}

// fill in the properites keys/values here
function properties() {
  return {
    "fill-color": "#ff0000",
    "tags": "",
    "FIPS": null,
    "name": ""
  };
}

function updateGeojson(geoJsonObject, feat) {

  let ff = geoJsonObject.features;

  if (ff.length === 0) {
    ff.push(feat);
    return featureCollection(ff);
  }

  indexOfFIPS = getFIPSByMap(geoJsonObject, feat);
  console.log("index of matching FIPS = " + indexOfFIPS);

  if (indexOfFIPS == -1) { // check if does not exist
    ff.push(feat);
  } else {
    console.log(ff[indexOfFIPS].properties["fill-color"], feat.properties["fill-color"]);
    if (ff[indexOfFIPS].properties["fill-color"] == feat.properties["fill-color"]) {
      // FIPS exists and colors match, remove
      console.log("remove FIPS");
      ff.splice(indexOfFIPS, 1);
    } else {
      // FIPS exists and colors are different, change color
      console.log("Update color and possibly tags");
      ff[indexOfFIPS].properties["fill-color"] = feat.properties["fill-color"];
      ff[indexOfFIPS].properties.tags = feat.properties.tags;
    }
  }

  return featureCollection(ff);

}

function getFIPSByMap(geoJsonObject, feat) {
  let features = geoJsonObject.features;
  let indexOfFIPS = -1;

  indexOfFIPS = features
    .map(function(v) {
      return v.properties.FIPS;
    })
    .indexOf(feat.properties.FIPS);

  return indexOfFIPS;
}

function getFIPSByColor(geoJsonObject) {

  value = [];
  colors = [];

  // first create an array, pushing only unique colors
  for (var f of geoJsonObject.features) {
    fillColor = f.properties['fill-color'];

    // add only unique colors to this array
    if (colors.indexOf(fillColor) == -1) {
      colors.push(fillColor);
    }
  }

  // now iterate overall features, again, to add FIPS
  for (var c of colors) {
    uniqueFips = [];

    for (var ff of geoJsonObject.features) {
      fillColor = ff.properties['fill-color'];
      FIPS = ff.properties.FIPS;

      if (c == fillColor & FIPS !== undefined) {
        // color exists, so push only the FIPS value
        uniqueFips.push(FIPS);
      }
    }

    colorFIPS = {
      color: '#123456',
      FIPS: []
    };

    colorFIPS.color = c;
    colorFIPS.FIPS = uniqueFips;

    value.push(colorFIPS);
  }

  return value;
}

function findByColor(colors, findColor) {
  for (var c of colors) {
    if (findColor == c.color) {
      return c.FIPS;
    }
  }
}

////
/// color picker
////
$("#overlay").mouseleave(function() {

});

var swatches = document.getElementById('swatches');

paletteColors.forEach(function(color) {

  var swatch = document.createElement('button');
  swatch.style.backgroundColor = color;

  swatch.addEventListener('mouseover', function() {
    console.log(color);
  });

  swatch.addEventListener('click', function() {

    if (FEATURE === null) {
      console.log("No FEATURE chosen, exiting");
      return;
    }

    console.log(color);

    let t = $("input[name='tags']").tagsinput('items');
    FEATURE.properties.tags = t.toString();
    FEATURE.properties["fill-color"] = color;

    // Create local copy, and pass that by value rather than the global
    p = point([FEATURE.geometry.coordinates[0], FEATURE.geometry.coordinates[1]]);
    f = feature(p);
    f.properties.FIPS = FEATURE.properties.FIPS;
    f.properties["fill-color"] = color;
    f.properties.name = FEATURE.properties.name;
    f.properties.tags = FEATURE.properties.tags;
    // add the new clicked feature to the geojson
    geojson = updateGeojson(geojson, f);

    // add border when county is DE-selected
    filter = baseFilter;
    map.setFilter("county-border", filter);

    setPaintColors(geojson);

    // update the database
    firebase.database().ref(databaseEndpoint).set({
      geojson: geojson
    });

  });
  swatches.appendChild(swatch);

});

function rawColorValue(color) {
  // color looks like #123456
  //   strip off the '#'
  return color.split('#')[1];
}

function addLayer(color) {

  var colorValue = rawColorValue(color);

  var layer = {
    "id": "counties-highlighted-" + colorValue,
    "type": "fill",
    "source": "counties",
    "source-layer": "original",
    "paint": {
      "fill-outline-color": colorHighlightedCounty,
      "fill-color": color,
    },
    "filter": baseFilter
  };

  return layer;
}

function addCountyBorderLayer() {

  var layer = {
    "id": "county-border",
    "type": "line",
    "source": "counties",
    "source-layer": "original",
    "paint": {
      "line-color": "#000000",
      "line-width": 2
    },
    "filter": baseFilter
  };

  return layer;
}

// jQuery
$(function() {

  $("[name='city-county-checkbox']").bootstrapSwitch();

  $('input').on('change', function(event) {

    var $element = $(event.target);
    var $container = $element.closest('.example');

    if (!$element.data('tagsinput'))
      return;

    var val = $element.val();
    if (val === null)
      val = "null";
    var items = $element.tagsinput('items');

  }).trigger('change');
});
<commit_msg>/codepen.io/mapbox-highlight-by-us-county * Opacity is now a parameter to the color palette<commit_after>/*jshint esversion: 6 */ /*jslint single*/
console.clear();

// Firebase
var database = firebase.database();
var databaseEndpoint = '/beta/';

// GeoJSON objects
var geojson = featureCollection([]);
var FEATURE = null; // create empty feature

// FIPS are unique codes for a county
var FIPS = [];
var tags = [];
var filter;
var baseFilter = ['in', 'FIPS'];

var colorHighlightedCounty = "#888888";
var OPACITY = 0.5;
var paletteColors = [
  '#ffffcc', '#a1dab4', '#41b6c4', '#2c7fb8', '#253494',
  '#fed976', '#feb24c', '#fd8d3c', '#f03b20', '#bd0026'
];

// http://stackoverflow.com/a/36253499
function hexToRGBA(hex, opacity) {
  return 'rgba(' + (hex = hex.replace('#', '')).match(new RegExp('(.{' + hex.length / 3 + '})', 'g')).map(function(l) {
    return parseInt(hex.length % 2 ? l + l : l, 16)
  }).concat(opacity || 1).join(',') + ')';
}

// Mapbox map
var map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v9',
  center: [-98, 38.88],
  minZoom: 2,
  zoom: 3
});

var overlay = document.getElementById('map-overlay');

// Create a popup, but don't add it to the map yet.
var popup = new mapboxgl.Popup({
  closeButton: false
});

map.on('load', function() {
  // Add the source to query. In this example we're using
  // county polygons uploaded as vector tiles
  map.addSource('counties', {
    "type": "vector",
    "url": "mapbox://mapbox.82pkq93d"
  });

  map.addLayer({
    "id": "counties",
    "type": "fill",
    "source": "counties",
    "source-layer": "original",
    "paint": {
      "fill-outline-color": "rgba(0,0,0,0.1)",
      "fill-color": "rgba(0,0,0,0.1)"
    }
  }, 'place-city-sm'); // Place polygon under these labels.

  paletteColors.forEach(function(color) {
    lay = addLayer(color);
    map.addLayer(lay, 'place-city-sm'); // Place polygon under these labels.)
  });

  // Border highlighted layer
  map.addLayer(addCountyBorderLayer(), 'place-city-sm');

  // Database
  var databaseObject = [];
  var rootRef = firebase.database().ref(databaseEndpoint);
  rootRef.once('value', function(snapshot) {

    if (snapshot.val() !== null) {
      databaseObject = snapshot.val();
      // the endpoint, or name of the object in the database is 'geojson/'
      //   so simplifiy the name by extracting the data by the name of 'geojson'
      geojson = databaseObject.geojson;

      if (geojson.features !== undefined) {
        setPaintColors(geojson);
      } else { // data base is NOT empty, but has no features
        geojson = featureCollection([]);
      }

    } else { // data base is empty
      geojson = featureCollection([]);
    }
  });

  map.on('click', function(e) {
    console.log('click');

    let queryFeature;
    // let checkbox = $('input[name="city-county-checkbox"]').bootstrapSwitch('state');
    checkbox = false; // TODO hardcode to false = County

    // Since we clicked on a new feature, nullify the previous one
    FEATURE = null;

    // Create a new GeoJson feature and properties
    let p = point([e.lngLat.lng, e.lngLat.lat]);
    FEATURE = feature(p);

    //
    if (checkbox === true) { // City
      queryFeature = map.queryRenderedFeatures(e.point);
      FEATURE.properties.name = queryFeature[0].properties.name;
    } else { // County
      queryFeature = map.queryRenderedFeatures(e.point, {
        layers: ['counties']
      });

      FEATURE.properties.FIPS = queryFeature[0].properties.FIPS;
      FEATURE.properties.name = queryFeature[0].properties.COUNTY;

      // add border when county is selected
      filter = baseFilter;
      filter = filter.concat(FEATURE.properties.FIPS);
      map.setFilter("county-border", filter);
    }

    // compare geojson for the current FIPS value, then extract the tags to update the UI
    indexOfFIPS = getFIPSByMap(geojson, FEATURE);
    if (indexOfFIPS != -1) {
      let t = geojson.features[indexOfFIPS].properties.tags;
      $("input[name='tags']").tagsinput('removeAll');
      $("input[name='tags']").tagsinput('add', t);
    }

    $(".county").html(FEATURE.properties.name);

  });

  map.on('mousemove', function(e) {
    var features = map.queryRenderedFeatures(e.point, {
      layers: ['counties']
    });

    // Change the cursor style as a UI indicator.
    map.getCanvas().style.cursor = features.length ? 'pointer' : '';

    // Remove things if no feature was found.
    if (!features.length) {
      popup.remove();
      // map.setFilter('counties-highlighted', ['in', 'COUNTY', '']);
      // overlay.style.display = 'none';
      return;
    }

    // Single out the first found feature on mouseove.
    var feature = features[0];

    // Query the counties layer visible in the map. Use the filter
    // param to only collect results that share the same county name.
    var relatedFeatures = map.querySourceFeatures('counties', {
      sourceLayer: 'original',
      filter: ['in', 'COUNTY', feature.properties.COUNTY]
    });

    // Display a popup with the name of the county
    popup.setLngLat(e.lngLat)
      .setText(feature.properties.COUNTY)
      .addTo(map);
  });
});

/////
function setPaintColors(geoJsonObject) {

  byColor = getFIPSByColor(geoJsonObject);

  // Special case when trying to remove the 'last' county
  if (byColor.length === 0) {
    filter = baseFilter;
    filter = filter.concat('[ ]');
    map.setFilter(layer, filter);
    return;
  }

  // Remove layers for each color to ensure UI is updated
  // Then replace each
  paletteColors.forEach(function(color) {
    rawCurrentColor = rawColorValue(color);
    layer = 'counties-highlighted-' + rawCurrentColor;
    map.removeLayer(layer);

    lay = addLayer(color);
    map.addLayer(lay, 'place-city-sm'); // Place polygon under these labels.)
  });

  byColor.forEach(function(colorRow) {
    color = colorRow.color;
    rawCurrentColor = rawColorValue(color);
    layer = 'counties-highlighted-' + rawCurrentColor;

    filter = baseFilter;
    filter = filter.concat(colorRow.FIPS);

    map.setFilter(layer, filter);
  });
}
/////

// GeoJson objects

// main geojson key
function featureCollection(f) {
  return {
    type: 'FeatureCollection',
    features: f
  };
}

// generate a geojson feature
function feature(geom) {
  return {
    type: 'Feature',
    geometry: geom,
    properties: properties()
  };
}

//  expects [longitude, latitude]
function point(coordinates) {
  return {
    type: 'Point',
    coordinates: coordinates
  };
}

// fill in the properites keys/values here
function properties() {
  return {
    "fill-color": "#ff0000",
    "tags": "",
    "FIPS": null,
    "name": ""
  };
}

function updateGeojson(geoJsonObject, feat) {

  let ff = geoJsonObject.features;

  if (ff.length === 0) {
    ff.push(feat);
    return featureCollection(ff);
  }

  indexOfFIPS = getFIPSByMap(geoJsonObject, feat);
  console.log("index of matching FIPS = " + indexOfFIPS);

  if (indexOfFIPS == -1) { // check if does not exist
    ff.push(feat);
  } else {
    console.log(ff[indexOfFIPS].properties["fill-color"], feat.properties["fill-color"]);
    if (ff[indexOfFIPS].properties["fill-color"] == feat.properties["fill-color"]) {
      // FIPS exists and colors match, remove
      console.log("remove FIPS");
      ff.splice(indexOfFIPS, 1);
    } else {
      // FIPS exists and colors are different, change color
      console.log("Update color and possibly tags");
      ff[indexOfFIPS].properties["fill-color"] = feat.properties["fill-color"];
      ff[indexOfFIPS].properties.tags = feat.properties.tags;
    }
  }

  return featureCollection(ff);

}

function getFIPSByMap(geoJsonObject, feat) {
  let features = geoJsonObject.features;
  let indexOfFIPS = -1;

  indexOfFIPS = features
    .map(function(v) {
      return v.properties.FIPS;
    })
    .indexOf(feat.properties.FIPS);

  return indexOfFIPS;
}

function getFIPSByColor(geoJsonObject) {

  value = [];
  colors = [];

  // first create an array, pushing only unique colors
  for (var f of geoJsonObject.features) {
    fillColor = f.properties['fill-color'];

    // add only unique colors to this array
    if (colors.indexOf(fillColor) == -1) {
      colors.push(fillColor);
    }
  }

  // now iterate overall features, again, to add FIPS
  for (var c of colors) {
    uniqueFips = [];

    for (var ff of geoJsonObject.features) {
      fillColor = ff.properties['fill-color'];
      FIPS = ff.properties.FIPS;

      if (c == fillColor & FIPS !== undefined) {
        // color exists, so push only the FIPS value
        uniqueFips.push(FIPS);
      }
    }

    colorFIPS = {
      color: '#123456',
      FIPS: []
    };

    colorFIPS.color = c;
    colorFIPS.FIPS = uniqueFips;

    value.push(colorFIPS);
  }

  return value;
}

function findByColor(colors, findColor) {
  for (var c of colors) {
    if (findColor == c.color) {
      return c.FIPS;
    }
  }
}

////
/// color picker
////
$("#overlay").mouseleave(function() {

});

var swatches = document.getElementById('swatches');

paletteColors.forEach(function(color) {

  var swatch = document.createElement('button');
  swatch.style.backgroundColor = hexToRGBA(color, OPACITY);

  swatch.addEventListener('mouseover', function() {
    console.log(color);
  });

  swatch.addEventListener('click', function() {

    if (FEATURE === null) {
      console.log("No FEATURE chosen, exiting");
      return;
    }

    console.log(color);

    let t = $("input[name='tags']").tagsinput('items');
    FEATURE.properties.tags = t.toString();
    FEATURE.properties["fill-color"] = color;

    // Create local copy, and pass that by value rather than the global
    p = point([FEATURE.geometry.coordinates[0], FEATURE.geometry.coordinates[1]]);
    f = feature(p);
    f.properties.FIPS = FEATURE.properties.FIPS;
    f.properties["fill-color"] = color;
    f.properties.name = FEATURE.properties.name;
    f.properties.tags = FEATURE.properties.tags;
    // add the new clicked feature to the geojson
    geojson = updateGeojson(geojson, f);

    // add border when county is DE-selected
    filter = baseFilter;
    map.setFilter("county-border", filter);

    setPaintColors(geojson);

    // update the database
    firebase.database().ref(databaseEndpoint).set({
      geojson: geojson
    });

  });
  swatches.appendChild(swatch);

});

function rawColorValue(color) {
  // color looks like #123456
  //   strip off the '#'
  return color.split('#')[1];
}

function addLayer(color) {

  var colorValue = rawColorValue(color);

  var layer = {
    "id": "counties-highlighted-" + colorValue,
    "type": "fill",
    "source": "counties",
    "source-layer": "original",
    "paint": {
      "fill-outline-color": colorHighlightedCounty,
      "fill-color": hexToRGBA(color, OPACITY)
    },
    "filter": baseFilter
  };

  return layer;
}

function addCountyBorderLayer() {

  var layer = {
    "id": "county-border",
    "type": "line",
    "source": "counties",
    "source-layer": "original",
    "paint": {
      "line-color": "#000000",
      "line-width": 2
    },
    "filter": baseFilter
  };

  return layer;
}

// jQuery
$(function() {

  $("[name='city-county-checkbox']").bootstrapSwitch();

  $('input').on('change', function(event) {

    var $element = $(event.target);
    var $container = $element.closest('.example');

    if (!$element.data('tagsinput'))
      return;

    var val = $element.val();
    if (val === null)
      val = "null";
    var items = $element.tagsinput('items');

  }).trigger('change');
});
<|endoftext|>


<commit_before>"use strict";

//-----------------------------------------------------------------------------

const [processPath, , exchangeId, methodName, ... params] = process.argv.filter (x => !x.startsWith ('--'))
const verbose = process.argv.includes ('--verbose')

//-----------------------------------------------------------------------------

const ccxt      = require ('../../ccxt.js')
    , fs        = require ('fs')
    , path      = require ('path')
    , asTable   = require ('as-table')
    , util      = require ('util')
    , log       = require ('ololog').configure ({ locate: false })

//-----------------------------------------------------------------------------

require ('ansicolor').nice;

//-----------------------------------------------------------------------------

process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })

//-----------------------------------------------------------------------------

const exchange = new (ccxt)[exchangeId] ({ verbose })

//-----------------------------------------------------------------------------

// set up keys and settings, if any
const keysGlobal = path.resolve ('keys.json')
const keysLocal = path.resolve ('keys.local.json')

log.red (keysGlobal)
log.red (keysLocal)

process.exit ()

let globalKeysFile = fs.existsSync (keysGlobal) ? keysGlobal : false
let localKeysFile = fs.existsSync (keysLocal) ? keysLocal : globalKeysFile
let settings = localKeysFile ? (require ('../../' + localKeysFile)[exchangeId] || {}) : {}

Object.assign (exchange, settings)

//-----------------------------------------------------------------------------

let printSupportedExchanges = function () {
    log ('Supported exchanges:', ccxt.exchanges.join (', ').green)
}

//-----------------------------------------------------------------------------

 function printUsage () {
    log ('This is an example of a basic command-line interface to all exchanges')
    log ('Usage: node', process.argv[1], 'id'.green, 'method'.yellow, '"param1" param2 "param3" param4 ...'.blue)
    log ('Examples:')
    log ('node', process.argv[1], 'okcoinusd fetchOHLCV BTC/USD 15m')
    log ('node', process.argv[1], 'bitfinex fetchBalance')
    log ('node', process.argv[1], 'kraken fetchOrderBook ETH/BTC')
    printSupportedExchanges ()
}

//-----------------------------------------------------------------------------

async function main () {

    const requirements = exchangeId && methodName
    if (!requirements) {

        printUsage ()

    } else {

        let args = params.map (param =>
            param.match (/[a-zA-Z]/g) ? param : parseFloat (param))

        console.log (await exchange[methodName] (... args))

    }
}

//-----------------------------------------------------------------------------

main ()
<commit_msg>minor edit<commit_after>"use strict";

//-----------------------------------------------------------------------------

const [processPath, , exchangeId, methodName, ... params] = process.argv.filter (x => !x.startsWith ('--'))
const verbose = process.argv.includes ('--verbose')

//-----------------------------------------------------------------------------

const ccxt      = require ('../../ccxt.js')
    , fs        = require ('fs')
    , path      = require ('path')
    , asTable   = require ('as-table')
    , util      = require ('util')
    , log       = require ('ololog').configure ({ locate: false })

//-----------------------------------------------------------------------------

require ('ansicolor').nice;

//-----------------------------------------------------------------------------

process.on ('uncaughtException',  e => { log.bright.red.error (e); process.exit (1) })
process.on ('unhandledRejection', e => { log.bright.red.error (e); process.exit (1) })

//-----------------------------------------------------------------------------

const exchange = new (ccxt)[exchangeId] ({ verbose })

//-----------------------------------------------------------------------------

// set up keys and settings, if any
const keysGlobal = path.resolve ('keys.json')
const keysLocal = path.resolve ('keys.local.json')

let globalKeysFile = fs.existsSync (keysGlobal) ? keysGlobal : false
let localKeysFile = fs.existsSync (keysLocal) ? keysLocal : globalKeysFile
let settings = localKeysFile ? (require (localKeysFile)[exchangeId] || {}) : {}

Object.assign (exchange, settings)

//-----------------------------------------------------------------------------

let printSupportedExchanges = function () {
    log ('Supported exchanges:', ccxt.exchanges.join (', ').green)
}

//-----------------------------------------------------------------------------

 function printUsage () {
    log ('This is an example of a basic command-line interface to all exchanges')
    log ('Usage: node', process.argv[1], 'id'.green, 'method'.yellow, '"param1" param2 "param3" param4 ...'.blue)
    log ('Examples:')
    log ('node', process.argv[1], 'okcoinusd fetchOHLCV BTC/USD 15m')
    log ('node', process.argv[1], 'bitfinex fetchBalance')
    log ('node', process.argv[1], 'kraken fetchOrderBook ETH/BTC')
    printSupportedExchanges ()
}

//-----------------------------------------------------------------------------

async function main () {

    const requirements = exchangeId && methodName
    if (!requirements) {

        printUsage ()

    } else {

        let args = params.map (param =>
            param.match (/[a-zA-Z]/g) ? param : parseFloat (param))

        console.log (await exchange[methodName] (... args))

    }
}

//-----------------------------------------------------------------------------

main ()
<|endoftext|>


<commit_before><commit_msg>removed files<commit_after><|endoftext|>


<commit_before>module.exports = {
  future: {
    removeDeprecatedGapUtilities: true,
  },
  purge: ['./components/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {
      colors: {
        'accent-1': '#333',
      },
    },
  },
  variants: {},
  plugins: [],
}
<commit_msg>Improve with-tailwindcss example (#17742)<commit_after>module.exports = {
  future: {
    removeDeprecatedGapUtilities: true,
    purgeLayersByDefault: true,
  },
  purge: ['./components/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {
      colors: {
        'accent-1': '#333',
      },
    },
  },
  variants: {},
  plugins: [],
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
"use strict";
try {
    require.resolve('./config');
} catch (e) {
    console.log('config.js is missing, check config.js.example');
    process.exit();
}
var config = require('./config');
var express = require('express');
var app = express();
var expressWs = require('express-uws')(app);
//var server = require('http').createServer(app);
/*var WSS = require('uws').Server;
var wss = new WSS({
    host: config.ws_host,
    port: config.ws_port
});*/
var Mpd = require('mpd');
var basicAuth = require('basic-auth');
var mpd, np = {
    song: ''
};
var spawn = require('child_process').spawn;
var ipRangeCheck = require("ip-range-check");

var send = function(me, cmd, data) {
    if (me && me.readyState === 1) {
        var json = JSON.stringify({
            cmd: cmd,
            msg: data
        });
        me.send(json);
    }
}

var broadcast = function(cmd, data) {
    expressWs.getWss().clients.forEach(function(me) {
        if (me && me.readyState === 1) {
            var json = JSON.stringify({
                cmd: cmd,
                msg: data
            });
            me.send(json);
        }
    });
}

mpd = Mpd.connect({
    host: config.mpd_host,
    port: config.mpd_port
});
mpd.on('error', function(err) {
    console.log(err);
});
mpd.on('end', function() {
    console.log('MPD disconnected, quitting');
    process.exit(0);
});
mpd.on('connect', function() {
    console.log('MPD connected');
});
mpd.on('ready', function() {
    console.log('MPD ready');
    if (config.mpd_pass !== '') {
        mpd.sendCommand('password ' + config.mpd_pass, function(err, msg) {
            console.log(msg);
        });
    }
});
mpd.on('system-player', function() {
    mpd.sendCommand('status', function(err, msg) {
        broadcast('status', msg);
    });
});
mpd.on('system-options', function() {
    mpd.sendCommand('status', function(err, msg) {
        broadcast('status', msg);
    });
});
mpd.on('system-playlist', function() {
    mpd.sendCommand('playlistinfo', function(err, msg) {
        broadcast('playlistinfo', msg);
    });
});
mpd.on('system-stored_playlist', function() {
    mpd.sendCommand('listplaylists', function(err, msg) {
        broadcast('listplaylists', msg);
    });
});
mpd.on('system-database', function() {
    mpd.sendCommand('count "(base \'usb\')"', function(err, msg) {
        broadcast('count', msg);
    });
});

var auth = function(req, res, next) {
    if (config.http_user === '' && config.http_pass === '') {
        return next();
    }

    function unauthorized(res) {
        res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
        return res.sendStatus(401);
    }

    var user = basicAuth(req);

    if (!user || !user.name || !user.pass) {
        return unauthorized(res);
    }

    if (user.name === config.http_user && user.pass === config.http_pass) {
        return next();
    } else {
        return unauthorized(res);
    }
};

app.use(express.static(__dirname + '/bower_components'));
app.use(express.static(__dirname + '/static'));
app.get('/', auth, function(req, res, next) {
    res.sendFile(__dirname + '/index.html');
});
app.get('/np', function(req, res, next) {
    mpd.sendCommand('currentsong', function(err, msg) {
        res.setHeader('cache-control', 'no-cache');
        res.setHeader('content-type', 'text/plain; charset=utf-8');
        if (err) {
            res.send('');
            return;
        }
        var artistreg = /^Artist: (.*)$/gm;
        var titlereg = /^Title: (.*)$/gm;
        var artist = artistreg.exec(msg);
        var title = titlereg.exec(msg);
        if (artist !== null && title !== null) {
            np.song = artist[1].trim() + ' - ' + title[1].trim();
        } else {
            np.song = '';
        }
        res.send(np.song);
    });
});
app.get('/waveform', function(req, res, next) {
    mpd.sendCommand('currentsong', function(err, msg) {
        res.setHeader('cache-control', 'no-cache');
        if (err) {
            res.status(400);
            res.send(msg);
            return;
        }
        res.setHeader('content-type', 'image/png');
        var filereg = /^file: (.*)$/gm;
        var file = filereg.exec(msg);
        if (file !== null) {
            var waveform = spawn('wav2png', ['-w', '1800', '-h', '100', '-b', '2e3338ff', '-f', '00000000', '-o', '/tmp/waveform.png', config.music_dir + '/' + file[1]]);
            waveform.on('close', function(code) {
                console.log('wav2png exited with code ' + code)
                res.sendFile('/tmp/waveform.png');
            })
        }
    });
});

//wss.on('connection', function(client, request) {
app.ws('/', function(ws, req) {
    console.log('Client connected...');
    ws.on('message', function(data) {
        var ip = ws._socket.remoteAddress.replace(/^::ffff:/i, '');
        var forwardedFor = req.headers['x-forwarded-for'];

        if(config.trusted_proxies.indexOf(ip) != -1 && forwardedFor) {
            // Use the original IP provided by a trusted proxy
            ip = forwardedFor;
        }

        var cmd = data.split(' ')[0];
        var cli = ws;
        if(ipRangeCheck(ip, config.whitelist) || config.safecommands.indexOf(cmd) != -1) {
            if (cmd == 'addrandom') {
                spawn('sh', ['-c', 'mpc listall | shuf -n 1 | mpc add']);
            } else {
                mpd.sendCommand(data, function(err, msg) {
                    if (err) console.log(err);
                    send(cli, data, msg);
                });
            }
        }
    });
});

app.listen(config.http_port);
<commit_msg>add mpd config to addrandom<commit_after>#!/usr/bin/env node
"use strict";
try {
    require.resolve('./config');
} catch (e) {
    console.log('config.js is missing, check config.js.example');
    process.exit();
}
var config = require('./config');
var express = require('express');
var app = express();
var expressWs = require('express-uws')(app);
//var server = require('http').createServer(app);
/*var WSS = require('uws').Server;
var wss = new WSS({
    host: config.ws_host,
    port: config.ws_port
});*/
var Mpd = require('mpd');
var basicAuth = require('basic-auth');
var mpd, np = {
    song: ''
};
var spawn = require('child_process').spawn;
var ipRangeCheck = require("ip-range-check");

var send = function(me, cmd, data) {
    if (me && me.readyState === 1) {
        var json = JSON.stringify({
            cmd: cmd,
            msg: data
        });
        me.send(json);
    }
}

var broadcast = function(cmd, data) {
    expressWs.getWss().clients.forEach(function(me) {
        if (me && me.readyState === 1) {
            var json = JSON.stringify({
                cmd: cmd,
                msg: data
            });
            me.send(json);
        }
    });
}

mpd = Mpd.connect({
    host: config.mpd_host,
    port: config.mpd_port
});
mpd.on('error', function(err) {
    console.log(err);
});
mpd.on('end', function() {
    console.log('MPD disconnected, quitting');
    process.exit(0);
});
mpd.on('connect', function() {
    console.log('MPD connected');
});
mpd.on('ready', function() {
    console.log('MPD ready');
    if (config.mpd_pass !== '') {
        mpd.sendCommand('password ' + config.mpd_pass, function(err, msg) {
            console.log(msg);
        });
    }
});
mpd.on('system-player', function() {
    mpd.sendCommand('status', function(err, msg) {
        broadcast('status', msg);
    });
});
mpd.on('system-options', function() {
    mpd.sendCommand('status', function(err, msg) {
        broadcast('status', msg);
    });
});
mpd.on('system-playlist', function() {
    mpd.sendCommand('playlistinfo', function(err, msg) {
        broadcast('playlistinfo', msg);
    });
});
mpd.on('system-stored_playlist', function() {
    mpd.sendCommand('listplaylists', function(err, msg) {
        broadcast('listplaylists', msg);
    });
});
mpd.on('system-database', function() {
    mpd.sendCommand('count "(base \'usb\')"', function(err, msg) {
        broadcast('count', msg);
    });
});

var auth = function(req, res, next) {
    if (config.http_user === '' && config.http_pass === '') {
        return next();
    }

    function unauthorized(res) {
        res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
        return res.sendStatus(401);
    }

    var user = basicAuth(req);

    if (!user || !user.name || !user.pass) {
        return unauthorized(res);
    }

    if (user.name === config.http_user && user.pass === config.http_pass) {
        return next();
    } else {
        return unauthorized(res);
    }
};

app.use(express.static(__dirname + '/bower_components'));
app.use(express.static(__dirname + '/static'));
app.get('/', auth, function(req, res, next) {
    res.sendFile(__dirname + '/index.html');
});
app.get('/np', function(req, res, next) {
    mpd.sendCommand('currentsong', function(err, msg) {
        res.setHeader('cache-control', 'no-cache');
        res.setHeader('content-type', 'text/plain; charset=utf-8');
        if (err) {
            res.send('');
            return;
        }
        var artistreg = /^Artist: (.*)$/gm;
        var titlereg = /^Title: (.*)$/gm;
        var artist = artistreg.exec(msg);
        var title = titlereg.exec(msg);
        if (artist !== null && title !== null) {
            np.song = artist[1].trim() + ' - ' + title[1].trim();
        } else {
            np.song = '';
        }
        res.send(np.song);
    });
});
app.get('/waveform', function(req, res, next) {
    mpd.sendCommand('currentsong', function(err, msg) {
        res.setHeader('cache-control', 'no-cache');
        if (err) {
            res.status(400);
            res.send(msg);
            return;
        }
        res.setHeader('content-type', 'image/png');
        var filereg = /^file: (.*)$/gm;
        var file = filereg.exec(msg);
        if (file !== null) {
            var waveform = spawn('wav2png', ['-w', '1800', '-h', '100', '-b', '2e3338ff', '-f', '00000000', '-o', '/tmp/waveform.png', config.music_dir + '/' + file[1]]);
            waveform.on('close', function(code) {
                console.log('wav2png exited with code ' + code)
                res.sendFile('/tmp/waveform.png');
            })
        }
    });
});

//wss.on('connection', function(client, request) {
app.ws('/', function(ws, req) {
    console.log('Client connected...');
    ws.on('message', function(data) {
        var ip = ws._socket.remoteAddress.replace(/^::ffff:/i, '');
        var forwardedFor = req.headers['x-forwarded-for'];

        if(config.trusted_proxies.indexOf(ip) != -1 && forwardedFor) {
            // Use the original IP provided by a trusted proxy
            ip = forwardedFor;
        }

        var cmd = data.split(' ')[0];
        var cli = ws;
        if(ipRangeCheck(ip, config.whitelist) || config.safecommands.indexOf(cmd) != -1) {
            if (cmd == 'addrandom') {
                var mpd_conf = 'export MPD_PORT=' + config.mpd_port + ';export MPD_HOST=' + (config.mpd_pass != '' ? config.mpd_pass + '@' : '') + config.mpd_host + ';';
                spawn('sh', ['-c', mpd_conf + 'mpc listall | shuf -n 1 | mpc add']);
            } else {
                mpd.sendCommand(data, function(err, msg) {
                    if (err) console.log(err);
                    send(cli, data, msg);
                });
            }
        }
    });
});

app.listen(config.http_port);
<|endoftext|>


<commit_before>var express = require("express");
var logfmt = require("logfmt");
var app = express();

app.use(logfmt.requestLogger());

app.get('/', function(req, res) {
  res.send('I AM ALIVE');
});

app.get('/search', function(req, res) {
  if (req.query.q[0] === 'D' || req.query.q[0] === 'd') {
    return res.redirect('https://phab.trifacta.com/' + req.query.q.toUpperCase());
  }
  res.redirect('https://www.google.com/search?q=' + req.query.q)
});

var port = Number(process.env.PORT || 5000);
app.listen(port, function() {
  console.log("Listening on " + port);
});
<commit_msg>Add basic support for some common functionality<commit_after>var express = require("express");
var logfmt = require("logfmt");
var app = express();

function startsWith(str, starts){
  if (starts === '') return true;
  if (str == null || starts == null) return false;
  str = String(str); starts = String(starts);
  return str.length >= starts.length && str.slice(0, starts.length) === starts;
}

function diff(res, param) {
  return res.redirect('https://phab.trifacta.com/' + param.toUpperCase());
}

function alldiffs(res) {
  return res.redirect('https://phab.trifacta.com/differential/');
}

function macro(res, param) {
  if (param) {
    return res.redirect('https://phab.trifacta.com/macro/?nameLike=' + param);
  }
  return res.redirect('https://phab.trifacta.com/macro/');
}

function issue(res, param) {
  if (param) {
    return res.redirect('https://trifacta.atlassian.net/browse/' + param);
  }
  return res.redirect('https://trifacta.atlassian.net/issues/?filter=-1');
}

function conf(res, param) {
  if (param) {
    return res.redirect('https://trifacta.atlassian.net/wiki/dosearchsite.action?queryString=' + param);
  }
  return res.redirect('https://trifacta.atlassian.net/wiki/');
}

function pr(res, param) {
  if (param) {
    return res.redirect('https://bitbucket.org/trifacta/trifacta/pull-request/' + param + '/');
  }
  return res.redirect('https://bitbucket.org/trifacta/trifacta/pull-requests');
}

app.use(logfmt.requestLogger());

app.get('/ping', function(req, res) {
  res.send('I AM ALIVE');
});

app.get('/search', function(req, res) {
  var query = req.query.q
  if (query === 'diff') {
    return alldiffs(res);
  }
  if (query === 't') {
    return issue(res);
  }
  if (startsWith(query, 'd') || startsWith(query, 'D')) {
    return diff(res, query);
  }
  if (startsWith(query, 'TD-')) {
    return issue(res, query);
  }
  if (startsWith(query, 'PR')) {
    return pr(res, query.slice(2, query.length));
  }
  if (startsWith(query, 'w ')) {
    return conf(res, query.slice(2, query.length));
  }
  if (startsWith(query, 'macro ')) {
    return macro(res, query.slice(6, query.length));
  }
  if (query === 'macro') {
    return macro(res);
  }
  res.redirect('https://www.google.com/search?q=' + req.query.q)
});

var port = Number(process.env.PORT || 5000);
app.listen(port, function() {
  console.log("Listening on " + port);
});
<|endoftext|>


<commit_before>'use strict';

// ----------------------------------------------------------------------------
// one half-side of an orderbook (bids or asks)
// overwrites absolute volumes at price levels

class OrderBookSide extends Array {

    // static get [Symbol.species] () { return Array }

    constructor (deltas = []) {
        super (deltas.length)
        // a string-keyed dictionary of price levels / ids / indices
        Object.defineProperty (this, 'index', {
            __proto__: null, // make it invisible
            value: {},
        })
        if (deltas.length) {
            this.update (deltas)
        }
    }

    // called for each orderbook update/frame/nonce with new incoming deltas
    update (deltas) {
        for (let i = 0; i < deltas.length; i++) {
            this.storeArray (deltas[i])
        }
        return this.limit ()
    }

    store (price, size) {
        if (size) {
            this.index[price] = size // absolute volume at price level
        } else {
            delete this.index[price] // purge zero values
        }
    }

    // index an incoming delta in the string-price-keyed dictionary
    storeArray (delta) {
        // const [ price, size ] = delta
        const price = delta[0]
        const size = delta[1]
        this.store (price, size)
    }

    // replace stored orders with new values
    limit (n = undefined) {
        const array = Object.entries (this.index).map (this.convert).sort (this.compare)
        n = Math.min (n || Number.MAX_SAFE_INTEGER, array.length)
        // the following lines could be written as
        //     this.splice (0, this.length, ... array)
        // however, both .splice and .slice copy-construct the arrays
        // so we assign the elements manually in favor of splice and slice
        for (let i = 0; i < n; i++) {
            this[i] = array[i]
        }
        // truncate the array by setting the length
        // which is a legitimate operation in JS
        this.length = n
        return this
    }

    // convert from string-keyed dict values to human types for userland
    convert ([ price, size ]) {
        return [ Number (price), size ]
    }
}

// ----------------------------------------------------------------------------
// some exchanges limit the number of bids/asks in the aggregated orderbook
// orders beyond the limit threshold are not updated with new ws deltas
// those orders should not be returned to the user, they are outdated quickly

class LimitedOrderBookSide extends OrderBookSide {

    constructor (deltas = [], depth = undefined) {
        super (deltas)
        Object.defineProperty (this, 'depth', {
            __proto__: null, // make it invisible
            value: depth,
        })
    }

    limit (n = undefined) {
        if (n) {
            return super.limit (Math.min (this.depth || Number.MAX_SAFE_INTEGER, n))
        } else {
            return super.limit (this.depth)
        }
    }
}

// ----------------------------------------------------------------------------
// overwrites absolute volumes at price levels
// or deletes price levels based on order counts (3rd value in a bidask delta)

class CountedOrderBookSide extends OrderBookSide {

    store (price, size, count) {
        if (count) {
            if (size) {
                this.index[price] = [ price, size, count ]
            } else {
                delete this.index[price]
            }
        } else {
            delete this.index[price]
        }
    }

    storeArray (delta) {
        const [ price, size, count ] = delta
        if (count) {
            if (size) {
                this.index[price] = delta
            } else {
                delete this.index[price]
            }
        } else {
            delete this.index[price]
        }
    }

    convert ([ _, [ price, size, count ]]) {
        return [ price, size, count ]
    }
}

// ----------------------------------------------------------------------------
// indexed by order ids (3rd value in a bidask delta)

class IndexedOrderBookSide extends OrderBookSide {

    store (price, size, id) {
        if (size) {
            this.index[id] = [ price, size, id ]
        } else {
            delete this.index[id]
        }
    }

    storeArray (delta) {
        // const [ price, size, id ] = delta
        // const price = delta[0]
        const size = delta[1]
            , id = delta[2]
        if (size) {
            this.index[id] = delta
        } else {
            delete this.index[id]
        }
    }

    convert ([ _, [ price, size, id ]]) {
        return [ price, size, id ]
    }
}

// ----------------------------------------------------------------------------
// adjusts the volumes by positive or negative relative changes or differences

class IncrementalOrderBookSide extends OrderBookSide {

    store (price, size) {
        if (size) {
            this.index[price] = (this.index[price] || 0) + size
            if (!this.index[price]) {
                delete this.index[price]
            }
        } else {
            delete this.index[price]
        }
    }
}

// ----------------------------------------------------------------------------
// incremental and indexed (2 in 1)

class IncrementalIndexedOrderBookSide extends IndexedOrderBookSide {

    store (price, size, id) {
        if (size) {
            size = (this.index[id] ? this.index[id][1] : 0) + size
            if (size) {
                this.index[id] = [ price, size, id ]
            } else {
                delete this.index[id]
            }
        } else {
            delete this.index[id]
        }
    }

    storeArray (delta) {
        // const [ price, size, id ] = delta
        const price = delta[0]
            , size = delta[1]
            , id = delta[2]
        this.store (price, size, id)
    }
}

// ----------------------------------------------------------------------------
// a more elegant syntax is possible here, but native inheritance is portable

class Asks extends OrderBookSide { compare (a, b) { return a[0] - b[0] }}
class Bids extends OrderBookSide { compare (a, b) { return b[0] - a[0] }}
class LimitedAsks extends LimitedOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class LimitedBids extends LimitedOrderBookSide { compare (a, b) { return b[0] - a[0] }}
class CountedAsks extends CountedOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class CountedBids extends CountedOrderBookSide { compare (a, b) { return b[0] - a[0] }}
class IndexedAsks extends IndexedOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class IndexedBids extends IndexedOrderBookSide { compare (a, b) { return b[0] - a[0] }}
class IncrementalAsks extends IncrementalOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class IncrementalBids extends IncrementalOrderBookSide { compare (a, b) { return b[0] - a[0] }}
class IncrementalIndexedAsks extends IncrementalIndexedOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class IncrementalIndexedBids extends IncrementalIndexedOrderBookSide { compare (a, b) { return b[0] - a[0] }}

// ----------------------------------------------------------------------------

module.exports = {

    // basic
    Asks,
    Bids,
    OrderBookSide,

    // limited
    LimitedAsks,
    LimitedBids,
    LimitedOrderBookSide,

    // count-based
    CountedAsks,
    CountedBids,
    CountedOrderBookSide,

    // order-id based
    IndexedAsks,
    IndexedBids,
    IndexedOrderBookSide,

    // incremental
    IncrementalAsks,
    IncrementalBids,
    IncrementalOrderBookSide,

    // order-id + incremental
    IncrementalIndexedAsks,
    IncrementalIndexedBids,
    IncrementalIndexedOrderBookSide,
}
<commit_msg>/js/base/OrderBookSide.js<commit_after>'use strict';

// ----------------------------------------------------------------------------
// one half-side of an orderbook (bids or asks)
// overwrites absolute volumes at price levels

class OrderBookSide extends Array {

    // static get [Symbol.species] () { return Array }

    constructor (deltas = []) {
        super (deltas.length)
        // a string-keyed dictionary of price levels / ids / indices
        Object.defineProperty (this, 'index', {
            __proto__: null, // make it invisible
            value: {},
        })
        if (deltas.length) {
            this.update (deltas)
        }
    }

    // called for each orderbook update/frame/nonce with new incoming deltas
    update (deltas) {
        for (let i = 0; i < deltas.length; i++) {
            this.storeArray (deltas[i])
        }
        return this.limit ()
    }

    store (price, size) {
        if (size) {
            this.index[price] = size // absolute volume at price level
        } else {
            delete this.index[price] // purge zero values
        }
    }

    // index an incoming delta in the string-price-keyed dictionary
    storeArray (delta) {
        // const [ price, size ] = delta
        const price = delta[0]
        const size = delta[1]
        this.store (price, size)
    }

    // replace stored orders with new values
    limit (n = undefined) {
        const array = Object.entries (this.index).map (this.convert).sort (this.compare)
        n = Math.min (n || Number.MAX_SAFE_INTEGER, array.length)
        // the following lines could be written as
        //     this.splice (0, this.length, ... array)
        // however, both .splice and .slice copy-construct the arrays
        // so we assign the elements manually in favor of splice and slice
        for (let i = 0; i < n; i++) {
            this[i] = array[i]
        }
        // truncate the array by setting the length
        // which is a legitimate operation in JS
        this.length = n
        return this
    }

    // convert from string-keyed dict values to human types for userland
    convert ([ price, size ]) {
        return [ Number (price), size ]
    }
}

// ----------------------------------------------------------------------------
// some exchanges limit the number of bids/asks in the aggregated orderbook
// orders beyond the limit threshold are not updated with new ws deltas
// those orders should not be returned to the user, they are outdated quickly

class LimitedOrderBookSide extends OrderBookSide {

    constructor (deltas = [], depth = undefined) {
        super (deltas)
        Object.defineProperty (this, 'depth', {
            __proto__: null, // make it invisible
            value: depth,
        })
    }

    limit (n = undefined) {
        const depth = n ? Math.min (this.depth || Number.MAX_SAFE_INTEGER, n) : this.depth
        const result = super.limit (depth)
        // have to reset the index here :(
        this.index = Object.fromEntries (result)
        return result
    }
}

// ----------------------------------------------------------------------------
// overwrites absolute volumes at price levels
// or deletes price levels based on order counts (3rd value in a bidask delta)

class CountedOrderBookSide extends OrderBookSide {

    store (price, size, count) {
        if (count) {
            if (size) {
                this.index[price] = [ price, size, count ]
            } else {
                delete this.index[price]
            }
        } else {
            delete this.index[price]
        }
    }

    storeArray (delta) {
        const [ price, size, count ] = delta
        if (count) {
            if (size) {
                this.index[price] = delta
            } else {
                delete this.index[price]
            }
        } else {
            delete this.index[price]
        }
    }

    convert ([ _, [ price, size, count ]]) {
        return [ price, size, count ]
    }
}

// ----------------------------------------------------------------------------
// indexed by order ids (3rd value in a bidask delta)

class IndexedOrderBookSide extends OrderBookSide {

    store (price, size, id) {
        if (size) {
            this.index[id] = [ price, size, id ]
        } else {
            delete this.index[id]
        }
    }

    storeArray (delta) {
        // const [ price, size, id ] = delta
        // const price = delta[0]
        const size = delta[1]
            , id = delta[2]
        if (size) {
            this.index[id] = delta
        } else {
            delete this.index[id]
        }
    }

    convert ([ _, [ price, size, id ]]) {
        return [ price, size, id ]
    }
}

// ----------------------------------------------------------------------------
// adjusts the volumes by positive or negative relative changes or differences

class IncrementalOrderBookSide extends OrderBookSide {

    store (price, size) {
        if (size) {
            this.index[price] = (this.index[price] || 0) + size
            if (!this.index[price]) {
                delete this.index[price]
            }
        } else {
            delete this.index[price]
        }
    }
}

// ----------------------------------------------------------------------------
// incremental and indexed (2 in 1)

class IncrementalIndexedOrderBookSide extends IndexedOrderBookSide {

    store (price, size, id) {
        if (size) {
            size = (this.index[id] ? this.index[id][1] : 0) + size
            if (size) {
                this.index[id] = [ price, size, id ]
            } else {
                delete this.index[id]
            }
        } else {
            delete this.index[id]
        }
    }

    storeArray (delta) {
        // const [ price, size, id ] = delta
        const price = delta[0]
            , size = delta[1]
            , id = delta[2]
        this.store (price, size, id)
    }
}

// ----------------------------------------------------------------------------
// a more elegant syntax is possible here, but native inheritance is portable

class Asks extends OrderBookSide { compare (a, b) { return a[0] - b[0] }}
class Bids extends OrderBookSide { compare (a, b) { return b[0] - a[0] }}
class LimitedAsks extends LimitedOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class LimitedBids extends LimitedOrderBookSide { compare (a, b) { return b[0] - a[0] }}
class CountedAsks extends CountedOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class CountedBids extends CountedOrderBookSide { compare (a, b) { return b[0] - a[0] }}
class IndexedAsks extends IndexedOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class IndexedBids extends IndexedOrderBookSide { compare (a, b) { return b[0] - a[0] }}
class IncrementalAsks extends IncrementalOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class IncrementalBids extends IncrementalOrderBookSide { compare (a, b) { return b[0] - a[0] }}
class IncrementalIndexedAsks extends IncrementalIndexedOrderBookSide { compare (a, b) { return a[0] - b[0] }}
class IncrementalIndexedBids extends IncrementalIndexedOrderBookSide { compare (a, b) { return b[0] - a[0] }}

// ----------------------------------------------------------------------------

module.exports = {

    // basic
    Asks,
    Bids,
    OrderBookSide,

    // limited
    LimitedAsks,
    LimitedBids,
    LimitedOrderBookSide,

    // count-based
    CountedAsks,
    CountedBids,
    CountedOrderBookSide,

    // order-id based
    IndexedAsks,
    IndexedBids,
    IndexedOrderBookSide,

    // incremental
    IncrementalAsks,
    IncrementalBids,
    IncrementalOrderBookSide,

    // order-id + incremental
    IncrementalIndexedAsks,
    IncrementalIndexedBids,
    IncrementalIndexedOrderBookSide,
}
<|endoftext|>


<commit_before>/**
 * Init script for admin functionality
 *
 * Created by Serhii Maksymchuk from Ubrainians for imCode
 * 07.08.17.
 */
Imcms.require(["imcms-admin-panel-builder", "imcms"], function (panelBuilder, imcms) {
    panelBuilder.buildPanel({active: imcms.isEditMode ? 'edit' : 'public'});
});
<commit_msg>IMCMS-233 - Apply new UI to the admin panel and editors: - Implemented editors load when in edit mode.<commit_after>/**
 * Init script for admin functionality
 *
 * Created by Serhii Maksymchuk from Ubrainians for imCode
 * 07.08.17.
 */
Imcms.require(["imcms-admin-panel-builder", "imcms"], function (panelBuilder, imcms) {
    panelBuilder.buildPanel({
        active: imcms.isEditMode ? 'edit' : 'public'
    });
    imcms.isEditMode && imcms.require("imcms-editors-initializer", function (editorsInit) {
        editorsInit.initEditors();
    });
});
<|endoftext|>


<commit_before>define(['jquery', 'backbone', 'underscore', 'moxie.conf'],
    function($, Backbone, _, conf) {
        var standardClass = 'ss-standard',
            favouriteClass = 'ss-star',
            favouritedClass = 'favourited';
        var FavouriteButtonView = Backbone.View.extend({
            initialize: function() {
                this.collection.on("reset remove add", this.updateButton, this);
            },
            manage: true,
            events: {'click': 'toggleFavourite'},
            tagName: 'a',
            attributes: {
                'class': [standardClass, favouriteClass].join(' ')
            },
            toggleFavourite: function(e) {
                e.preventDefault();
                var fav = this.collection.getCurrentPage();
                if (fav) {
                    this.removeFavourite(fav);
                } else {
                    this.addFavourite();
                }
            },
            afterRender: function() {
                this.updateButton();
            },
            addFavourite: function() {
                var fragment = Backbone.history.getFragment(undefined, undefined, true);
                var params = Backbone.history.getQueryParameters();
                var title = document.title.split(conf.titlePrefix, 2)[1];
                var path = Backbone.history.getFragment();
                this.collection.create({path: path, fragment: fragment, params: params, title: title},
                    {success: function(model) {
                        Backbone.trigger('favourited', model);
                    }
                });
            },
            removeFavourite: function(favourite) {
                this.collection.remove(favourite);
            },
            updateButton: function() {
                this.$el.toggleClass(favouritedClass, this.collection.currentPageFavourited());
            }
        });
        return FavouriteButtonView;
    }
);
<commit_msg>Added the hashchange listener back in<commit_after>define(['jquery', 'backbone', 'underscore', 'moxie.conf'],
    function($, Backbone, _, conf) {
        var standardClass = 'ss-standard',
            favouriteClass = 'ss-star',
            favouritedClass = 'favourited';
        var FavouriteButtonView = Backbone.View.extend({
            initialize: function() {
                this.collection.on("reset remove add", this.updateButton, this);
                // Specify a namespace on the event so we don't remove all listeners
                $(window).on("hashchange.FavouriteButton", _.bind(this.updateButton, this));
            },
            manage: true,
            events: {'click': 'toggleFavourite'},
            tagName: 'a',
            attributes: {
                'class': [standardClass, favouriteClass].join(' ')
            },
            toggleFavourite: function(e) {
                e.preventDefault();
                var fav = this.collection.getCurrentPage();
                if (fav) {
                    this.removeFavourite(fav);
                } else {
                    this.addFavourite();
                }
            },
            afterRender: function() {
                this.updateButton();
            },
            addFavourite: function() {
                var fragment = Backbone.history.getFragment(undefined, undefined, true);
                var params = Backbone.history.getQueryParameters();
                var title = document.title.split(conf.titlePrefix, 2)[1];
                var path = Backbone.history.getFragment();
                this.collection.create({path: path, fragment: fragment, params: params, title: title},
                    {success: function(model) {
                        Backbone.trigger('favourited', model);
                    }
                });
            },
            removeFavourite: function(favourite) {
                this.collection.remove(favourite);
            },
            updateButton: function() {
                this.$el.toggleClass(favouritedClass, this.collection.currentPageFavourited());
            },
            cleanup: function() {
                $(window).off("hashchange.FavouriteButton");
            }
        });
        return FavouriteButtonView;
    }
);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import Page from './Page';
import CustomDragLayer from './CustomDragLayer';
import ToolBox from './ToolBox'

class Canvas extends Component {
  constructor(props) {
    super(props);

    this.handleSnapToGridAfterDropChange = this.handleSnapToGridAfterDropChange.bind(this);
    this.handleSnapToGridWhileDraggingChange = this.handleSnapToGridWhileDraggingChange.bind(this);

    this.state = {
      snapToGridAfterDrop: false,
      snapToGridWhileDragging: false,
    };
  }

  componentDidMount() {

  }

  render() {
    const { snapToGridAfterDrop, snapToGridWhileDragging } = this.state;

    return (

        <ToolBox />
        <Page snapToGrid={snapToGridAfterDrop} />
        <CustomDragLayer snapToGrid={snapToGridWhileDragging} />

            <input
              id="snapToGridWhileDragging"
              type="checkbox"
              checked={snapToGridWhileDragging}
              onChange={this.handleSnapToGridWhileDraggingChange}
            />
            Snap to grid while dragging

            <input
              id="snapToGridAfterDrop"
              type="checkbox"
              checked={snapToGridAfterDrop}
              onChange={this.handleSnapToGridAfterDropChange}
            />
            Snap to grid after drop

    );
  }

  handleSnapToGridAfterDropChange() {
    this.setState({
      snapToGridAfterDrop: !this.state.snapToGridAfterDrop,
    });
  }

  handleSnapToGridWhileDraggingChange() {
    this.setState({
      snapToGridWhileDragging: !this.state.snapToGridWhileDragging,
    });
  }

}

export default DragDropContext(HTML5Backend)(Canvas)
<commit_msg>Update Canvas.js<commit_after>import React, { Component } from 'react';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import Page from './Page';
import CustomDragLayer from './CustomDragLayer';
import ToolBox from './ToolBox'

class Canvas extends Component {
  constructor(props) {
    super(props);

    this.handleSnapToGridAfterDropChange = this.handleSnapToGridAfterDropChange.bind(this);
    this.handleSnapToGridWhileDraggingChange = this.handleSnapToGridWhileDraggingChange.bind(this);

    this.state = {
      snapToGridAfterDrop: false,
      snapToGridWhileDragging: false,
    };
  }

  render() {
    const { snapToGridAfterDrop, snapToGridWhileDragging } = this.state;

    return (

        <ToolBox />
        <Page snapToGrid={snapToGridAfterDrop} />
        <CustomDragLayer snapToGrid={snapToGridWhileDragging} />

            <input
              id="snapToGridWhileDragging"
              type="checkbox"
              checked={snapToGridWhileDragging}
              onChange={this.handleSnapToGridWhileDraggingChange}
            />
            Snap to grid while dragging

            <input
              id="snapToGridAfterDrop"
              type="checkbox"
              checked={snapToGridAfterDrop}
              onChange={this.handleSnapToGridAfterDropChange}
            />
            Snap to grid after drop

    );
  }

  handleSnapToGridAfterDropChange() {
    this.setState({
      snapToGridAfterDrop: !this.state.snapToGridAfterDrop,
    });
  }

  handleSnapToGridWhileDraggingChange() {
    this.setState({
      snapToGridWhileDragging: !this.state.snapToGridWhileDragging,
    });
  }

}

export default DragDropContext(HTML5Backend)(Canvas)
<|endoftext|>


<commit_before>#!/usr/bin/env node
var cp = require('child_process'),
	fs = require('fs'),
	path = require('path');

// Parse args
var force = false, debug = false;
var
	arch = process.arch,
	platform = process.platform;
var args = process.argv.slice(2).filter(function(arg) {
	if (arg === '-f') {
		force = true;
		return false;
	} else if (arg.substring(0, 13) === '--target_arch') {
		arch = arg.substring(14);
	} else if (arg === '--debug') {
		debug = true;
	}
	return true;
});
if (!debug) {
	args.push('--release');
}
if (!{ia32: true, x64: true, arm: true, arm64: true, ppc: true, ppc64: true, s390: true, s390x: true}.hasOwnProperty(arch)) {
	console.error('Unsupported (?) architecture: `'+ arch+ '`');
	process.exit(1);
}

// Test for pre-built library
var modPath = platform+ '-'+ arch+ '-'+ process.versions.modules;
if (!force) {
	try {
		fs.statSync(path.join(__dirname, 'bin', modPath, 'fibers.node'));
		console.log('`'+ modPath+ '` exists; testing');
		cp.execFile(process.execPath, ['quick-test'], function(err, stdout, stderr) {
			if (err || stdout !== 'pass' || stderr) {
				console.log('Problem with the binary; manual build incoming');
				build();
			} else {
				console.log('Binary is fine; exiting');
			}
		});
	} catch (ex) {
		// Stat failed
		build();
	}
} else {
	build();
}

// Build it
function build() {
	cp.spawn(
		process.platform === 'win32' ? 'node-gyp.cmd' : 'node-gyp',
		['rebuild'].concat(args),
		{stdio: [process.stdin, process.stdout, process.stderr]})
	.on('exit', function(err) {
		if (err) {
			console.error(
				'node-gyp exited with code: '+ err+ '\n'+
				'Please make sure you are using a supported platform and node version. If you\n'+
				'would like to compile fibers on this machine please make sure you have setup your\n'+
				'build environment--\n'+
				'Windows + OS X instructions here: https://github.com/nodejs/node-gyp\n'+
				'Ubuntu users please run: `sudo apt-get install g++`\n'+
				'Alpine users please run: `sudo apk add python make g++`'
			);
			return process.exit(err);
		}
		afterBuild();
	})
	.on('error', function(err) {
		console.error(
			'node-gyp not found! Please ensure node-gyp is in your PATH--\n'+
			'Try running: `sudo npm install -g node-gyp`'
		);
		console.log(err.message);
		process.exit(1);
	});
}

// Move it to expected location
function afterBuild() {
	var targetPath = path.join(__dirname, 'build', debug ? 'Debug' : 'Release', 'fibers.node');
	var installPath = path.join(__dirname, 'bin', modPath, 'fibers.node');

	try {
		fs.mkdirSync(path.join(__dirname, 'bin', modPath));
	} catch (ex) {}

	try {
		fs.statSync(targetPath);
	} catch (ex) {
		console.error('Build succeeded but target not found');
		process.exit(1);
	}
	fs.renameSync(targetPath, installPath);
	console.log('Installed in `'+ installPath+ '`');
	if (process.versions.electron) {
		process.nextTick(function() {
			require('electron').app.quit();
		});
	}
}
<commit_msg>Update Ubuntu error message tip<commit_after>#!/usr/bin/env node
var cp = require('child_process'),
	fs = require('fs'),
	path = require('path');

// Parse args
var force = false, debug = false;
var
	arch = process.arch,
	platform = process.platform;
var args = process.argv.slice(2).filter(function(arg) {
	if (arg === '-f') {
		force = true;
		return false;
	} else if (arg.substring(0, 13) === '--target_arch') {
		arch = arg.substring(14);
	} else if (arg === '--debug') {
		debug = true;
	}
	return true;
});
if (!debug) {
	args.push('--release');
}
if (!{ia32: true, x64: true, arm: true, arm64: true, ppc: true, ppc64: true, s390: true, s390x: true}.hasOwnProperty(arch)) {
	console.error('Unsupported (?) architecture: `'+ arch+ '`');
	process.exit(1);
}

// Test for pre-built library
var modPath = platform+ '-'+ arch+ '-'+ process.versions.modules;
if (!force) {
	try {
		fs.statSync(path.join(__dirname, 'bin', modPath, 'fibers.node'));
		console.log('`'+ modPath+ '` exists; testing');
		cp.execFile(process.execPath, ['quick-test'], function(err, stdout, stderr) {
			if (err || stdout !== 'pass' || stderr) {
				console.log('Problem with the binary; manual build incoming');
				build();
			} else {
				console.log('Binary is fine; exiting');
			}
		});
	} catch (ex) {
		// Stat failed
		build();
	}
} else {
	build();
}

// Build it
function build() {
	cp.spawn(
		process.platform === 'win32' ? 'node-gyp.cmd' : 'node-gyp',
		['rebuild'].concat(args),
		{stdio: [process.stdin, process.stdout, process.stderr]})
	.on('exit', function(err) {
		if (err) {
			console.error(
				'node-gyp exited with code: '+ err+ '\n'+
				'Please make sure you are using a supported platform and node version. If you\n'+
				'would like to compile fibers on this machine please make sure you have setup your\n'+
				'build environment--\n'+
				'Windows + OS X instructions here: https://github.com/nodejs/node-gyp\n'+
				'Ubuntu users please run: `sudo apt-get install g++ build-essential`\n'+
				'Alpine users please run: `sudo apk add python make g++`'
			);
			return process.exit(err);
		}
		afterBuild();
	})
	.on('error', function(err) {
		console.error(
			'node-gyp not found! Please ensure node-gyp is in your PATH--\n'+
			'Try running: `sudo npm install -g node-gyp`'
		);
		console.log(err.message);
		process.exit(1);
	});
}

// Move it to expected location
function afterBuild() {
	var targetPath = path.join(__dirname, 'build', debug ? 'Debug' : 'Release', 'fibers.node');
	var installPath = path.join(__dirname, 'bin', modPath, 'fibers.node');

	try {
		fs.mkdirSync(path.join(__dirname, 'bin', modPath));
	} catch (ex) {}

	try {
		fs.statSync(targetPath);
	} catch (ex) {
		console.error('Build succeeded but target not found');
		process.exit(1);
	}
	fs.renameSync(targetPath, installPath);
	console.log('Installed in `'+ installPath+ '`');
	if (process.versions.electron) {
		process.nextTick(function() {
			require('electron').app.quit();
		});
	}
}
<|endoftext|>


<commit_before>var display_toast = {
    show_toast: function(successCallback, errorCallback, message) {
		cordova.exec( successCallback,
		            errorCallback,
					"Display_Toast",
					"Toast_method_called",
					[{
					 "message":message
					}]
					);
    }
}

module.exports = display_toast;

<commit_msg>Update display_toast.js<commit_after>var display_toast = {
    show_toast: function(successCallback, errorCallback, message) {
		cordova.exec( successCallback,
		            errorCallback,
					"Display_Toast",
					"Toast_method_called",
					message
					);
    }
}

module.exports = display_toast;

<|endoftext|>


<commit_before>// Description:
//   Let Hubot store daily status updates for your team
//
//   The output is tailored for Slack and assumes existence of Markdown's code markers,
//   but should work well for others as well.

//
// Commands:
//   hubot daily update help - List of commands
//   hubot my update is <message> - Tell hubot about an update. You can tell hubot about how many updates you want in a day.
//   hubot get daily updates by <username> - Gets all of today's updates for a user
//   hubot get daily updates - Gets all daily updates for all users for today
//   hubot get all daily updates for yesterday - Gets all daily updates for all users for yesterday
//   hubot get all daily updates for last week for <room> - Gets all daily updates for all users for last week (Maybe a good idea to always use this in private chat with me)
//   hubot get all daily updates for <X> days ago - Gets all daily updates for all users for X days ago
//   hubot remove daily updates on <YYYY-MM-DD> by <username> - Removes all updates on a given date by a given user
//   hubot remove daily updates by <username> - Removes all updates by a given user
//   hubot remove daily updates for room - Removes all updates for the current room
//
// Dependencies:
//   lodash
//   moment

var _ = require('lodash-node');
var moment = require('moment');

module.exports = function(robot) {

    robot.respond(/my update is (.*)/i, function(msg) {
      var dailyUpdate = msg.match[1];
      if(dailyUpdate.length > 0) {
        var username = msg.envelope.user.name;
        var room = msg.envelope.user.room;
        var today = getToday();
        var messages = getRoomMessages(room);
        messages[username] = messages[username] || {};
        messages[username][today] = messages[username][today] || [];
        messages[username][today].push(dailyUpdate);

        saveRoomMessages(room, messages);

        msg.send('added your daily update');
      } else {
        msg.send('Sorry, your update is empty. Try again');
      }
    });

    robot.respond(/get daily updates by (\w*)/i, function(msg) {
      var username = msg.match[1];
      var room = msg.envelope.user.room;
      var today = getToday();
      var messages = getRoomMessages(room);

      if(username.length === 0)
        return msg.send('You need to supply a user name');
      if(!(username in messages))
        return msg.send('This user does not exist or has never stored any updates');
      if(!(today in messages[username]) || messages[username][today].length === 0)
        return msg.send('No daily updates for this user yet');

      msg.send(
        'Daily update of '+today+' by '+username+':\n'+
        renderMessages(messages[username][today])+
        '\n'
      );
    });

    robot.respond(/get daily updates/i, function (msg) {
      if(msg.match.input.length === msg.match[0].length){
        var today = getToday();
        msg.send(getDailyUpdates(msg.envelope.user.room, today));
      }
    });

    robot.respond(/get all daily updates for yesterday/i, function (msg) {
      msg.send(getDailyUpdates(msg.envelope.user.room, getToday(-1)));
    });

    robot.respond(/get all daily updates for last week for (\w+)/i, function (msg) {
      var room = msg.match[1];
      var output = '';
      for(var i=7; i>=0; i--){
        output += getDailyUpdates(room, getToday(-i));
      }
      msg.send(output);
    });

    robot.respond(/get all daily updates for (\d+) days ago/i, function (msg) {
      var day = parseInt(msg.match[1], 10);
      msg.send(getDailyUpdates(msg.envelope.user.room, getToday(-day)));
    });

    robot.respond(/remove daily updates on ([\d|-]+) by (\w+)/i, function (msg) {
      var date = msg.match[1];
      var username = msg.match[2];
      var room = msg.envelope.user.room;
      var roomMessages = getRoomMessages(room);
      if(!(username in roomMessages))
        return msg.send(username+' had no updates anyway');
      if(!(date in roomMessages[username]))
        return msg.send(username+' had no updates on '+date+' anyway');
      roomMessages[username][date] = [];
      saveRoomMessages(room, roomMessages);
      msg.send('removed all updates for '+username+' on '+date);
    });

    robot.respond(/remove daily updates by (\w+)/i, function (msg) {
      var username = msg.match[1];
      var room = msg.envelope.user.room;
      var roomMessages = getRoomMessages(room);
      if(!(username in roomMessages))
        return msg.send(username+' had no updates anyway');
      roomMessages[username] = {};
      saveRoomMessages(room, roomMessages);
      msg.send('removed all updates for '+username);
    });

    robot.respond(/remove daily updates for room/i, function (msg) {
      var room = msg.envelope.user.room;
      saveRoomMessages(room, null);
      msg.send('removed all updates for '+room);
    });

    function getDailyUpdates(room, currentDay) {
      var messages = getRoomMessages(room);

      if(_.keys(messages).length === 0) {
        return 'No updates for '+currentDay+' yet';
      }

      var output = '';
      var day;
      _.each(messages, function (days, username) {
        output += 'Updates for '+username+' on '+currentDay+':\n';
        day = currentDay in days ? days[currentDay] : [];
        if(day.length > 0){
          output += renderMessages(day);
        } else {
          output += '- No updates yet';
        }
        output += '\n';
      });

      return output;
    }

    function getRoomMessages(room) {
      return robot.brain.get('daily-updates:'+room) || {};
    }

    function saveRoomMessages(room, messages) {
      robot.brain.set('daily-updates:'+room, messages);
    }

    function renderMessages(messages) {
      return _.map(messages, function (update) {
        return '- '+update;
      }).join('\n');
    }

    function getToday(minus) {
      var today = moment();
      if(minus) today.subtract(-minus, 'days');
      return today.format('YYYY-MM-DD');
    }

    robot.respond(/daily update help/i, function(msg) {
        var message = [];
        message.push("I'll store your status updates!");
        message.push("I can store as many status updates per day as you want. Just tell me about what you did. Here's how you can do it:");
        message.push("");
        message.push(robot.name + " my update is <message> - Tell hubot about an update. You can tell hubot about how many updates you want in a day.");
        message.push(robot.name + " get daily updates by <username> - Gets all of today's updates for a user");
        message.push(robot.name + " get daily updates - Gets all daily updates for all users for today");
        message.push(robot.name + " get all daily updates for yesterday - Gets all daily updates for all users for yesterday");
        message.push(robot.name + " get all daily updates for last week for <room> - Gets all daily updates for all users for last week (Maybe a good idea to always use this in private chat with me)");
        message.push(robot.name + " get all daily updates for <X> days ago - Gets all daily updates for all users for X days ago");
        message.push(robot.name + " remove daily updates on <YYYY-MM-DD> by <username> - Removes all updates on a given date by a given user");
        message.push(robot.name + " remove daily updates by <username> - Removes all updates by a given user");
        message.push(robot.name + " remove daily updates for room - Removes all updates for the current room");

        msg.send(message.join('\n'));
    });
};
<commit_msg>Fix regexp for weekly updates command<commit_after>// Description:
//   Let Hubot store daily status updates for your team
//
//   The output is tailored for Slack and assumes existence of Markdown's code markers,
//   but should work well for others as well.

//
// Commands:
//   hubot daily update help - List of commands
//   hubot my update is <message> - Tell hubot about an update. You can tell hubot about how many updates you want in a day.
//   hubot get daily updates by <username> - Gets all of today's updates for a user
//   hubot get daily updates - Gets all daily updates for all users for today
//   hubot get all daily updates for yesterday - Gets all daily updates for all users for yesterday
//   hubot get all daily updates for last week for <room> - Gets all daily updates for all users for last week (Maybe a good idea to always use this in private chat with me)
//   hubot get all daily updates for <X> days ago - Gets all daily updates for all users for X days ago
//   hubot remove daily updates on <YYYY-MM-DD> by <username> - Removes all updates on a given date by a given user
//   hubot remove daily updates by <username> - Removes all updates by a given user
//   hubot remove daily updates for room - Removes all updates for the current room
//
// Dependencies:
//   lodash
//   moment

var _ = require('lodash-node');
var moment = require('moment');

module.exports = function(robot) {

    robot.respond(/my update is (.*)/i, function(msg) {
      var dailyUpdate = msg.match[1];
      if(dailyUpdate.length > 0) {
        var username = msg.envelope.user.name;
        var room = msg.envelope.user.room;
        var today = getToday();
        var messages = getRoomMessages(room);
        messages[username] = messages[username] || {};
        messages[username][today] = messages[username][today] || [];
        messages[username][today].push(dailyUpdate);

        saveRoomMessages(room, messages);

        msg.send('added your daily update');
      } else {
        msg.send('Sorry, your update is empty. Try again');
      }
    });

    robot.respond(/get daily updates by (\w*)/i, function(msg) {
      var username = msg.match[1];
      var room = msg.envelope.user.room;
      var today = getToday();
      var messages = getRoomMessages(room);

      if(username.length === 0)
        return msg.send('You need to supply a user name');
      if(!(username in messages))
        return msg.send('This user does not exist or has never stored any updates');
      if(!(today in messages[username]) || messages[username][today].length === 0)
        return msg.send('No daily updates for this user yet');

      msg.send(
        'Daily update of '+today+' by '+username+':\n'+
        renderMessages(messages[username][today])+
        '\n'
      );
    });

    robot.respond(/get daily updates/i, function (msg) {
      if(msg.match.input.length === msg.match[0].length){
        var today = getToday();
        msg.send(getDailyUpdates(msg.envelope.user.room, today));
      }
    });

    robot.respond(/get all daily updates for yesterday/i, function (msg) {
      msg.send(getDailyUpdates(msg.envelope.user.room, getToday(-1)));
    });

    robot.respond(/get all daily updates for last week for ([#|\w|\d|_|-]+)/i, function (msg) {
      var room = msg.match[1];
      console.log(room);
      var output = '';
      for(var i=7; i>=0; i--){
        output += getDailyUpdates(room, getToday(-i))+'\n';
      }
      msg.send(output);
    });

    robot.respond(/get all daily updates for (\d+) days ago/i, function (msg) {
      var day = parseInt(msg.match[1], 10);
      msg.send(getDailyUpdates(msg.envelope.user.room, getToday(-day)));
    });

    robot.respond(/remove daily updates on ([\d|-]+) by (\w+)/i, function (msg) {
      var date = msg.match[1];
      var username = msg.match[2];
      var room = msg.envelope.user.room;
      var roomMessages = getRoomMessages(room);
      if(!(username in roomMessages))
        return msg.send(username+' had no updates anyway');
      if(!(date in roomMessages[username]))
        return msg.send(username+' had no updates on '+date+' anyway');
      roomMessages[username][date] = [];
      saveRoomMessages(room, roomMessages);
      msg.send('removed all updates for '+username+' on '+date);
    });

    robot.respond(/remove daily updates by (\w+)/i, function (msg) {
      var username = msg.match[1];
      var room = msg.envelope.user.room;
      var roomMessages = getRoomMessages(room);
      if(!(username in roomMessages))
        return msg.send(username+' had no updates anyway');
      roomMessages[username] = {};
      saveRoomMessages(room, roomMessages);
      msg.send('removed all updates for '+username);
    });

    robot.respond(/remove daily updates for room/i, function (msg) {
      var room = msg.envelope.user.room;
      saveRoomMessages(room, null);
      msg.send('removed all updates for '+room);
    });

    function getDailyUpdates(room, currentDay) {
      var messages = getRoomMessages(room);

      if(_.keys(messages).length === 0) {
        return 'No updates for '+currentDay+' yet';
      }

      var output = '';
      var day;
      _.each(messages, function (days, username) {
        output += 'Updates for '+username+' on '+currentDay+':\n';
        day = currentDay in days ? days[currentDay] : [];
        if(day.length > 0){
          output += renderMessages(day);
        } else {
          output += '- No updates yet';
        }
        output += '\n';
      });

      return output;
    }

    function getRoomMessages(room) {
      return robot.brain.get('daily-updates:'+room) || {};
    }

    function saveRoomMessages(room, messages) {
      robot.brain.set('daily-updates:'+room, messages);
    }

    function renderMessages(messages) {
      return _.map(messages, function (update) {
        return '- '+update;
      }).join('\n');
    }

    function getToday(minus) {
      var today = moment();
      if(minus) today.subtract(-minus, 'days');
      return today.format('YYYY-MM-DD');
    }

    robot.respond(/daily update help/i, function(msg) {
        var message = [];
        message.push("I'll store your status updates!");
        message.push("I can store as many status updates per day as you want. Just tell me about what you did. Here's how you can do it:");
        message.push("");
        message.push(robot.name + " my update is <message> - Tell hubot about an update. You can tell hubot about how many updates you want in a day.");
        message.push(robot.name + " get daily updates by <username> - Gets all of today's updates for a user");
        message.push(robot.name + " get daily updates - Gets all daily updates for all users for today");
        message.push(robot.name + " get all daily updates for yesterday - Gets all daily updates for all users for yesterday");
        message.push(robot.name + " get all daily updates for last week for <room> - Gets all daily updates for all users for last week (Maybe a good idea to always use this in private chat with me)");
        message.push(robot.name + " get all daily updates for <X> days ago - Gets all daily updates for all users for X days ago");
        message.push(robot.name + " remove daily updates on <YYYY-MM-DD> by <username> - Removes all updates on a given date by a given user");
        message.push(robot.name + " remove daily updates by <username> - Removes all updates by a given user");
        message.push(robot.name + " remove daily updates for room - Removes all updates for the current room");

        msg.send(message.join('\n'));
    });
};
<|endoftext|>


<commit_before>/* eslint global-require: 0 */
/* eslint import/no-dynamic-require: 0 */

const {
  basename, dirname, join, relative, resolve
} = require('path')
const { sync } = require('glob')
const extname = require('path-complete-extname')

const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const WebpackAssetsManifest = require('webpack-assets-manifest')
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
const PnpWebpackPlugin = require('pnp-webpack-plugin')

const { isNotObject, prettyPrint } = require('../utils/helpers')
const deepMerge = require('../utils/deep_merge')

const { ConfigList, ConfigObject } = require('../config_types')
const rules = require('../rules')
const config = require('../config')

const getLoaderList = () => {
  const result = new ConfigList()
  Object.keys(rules).forEach((key) => result.append(key, rules[key]))
  return result
}

const getPluginList = () => {
  const result = new ConfigList()
  result.append(
    'Environment',
    new webpack.EnvironmentPlugin(process.env)
  )
  result.append('CaseSensitivePaths', new CaseSensitivePathsPlugin())
  result.append(
    'MiniCssExtract',
    new MiniCssExtractPlugin({
      filename: 'css/[name]-[contenthash:8].css',
      chunkFilename: 'css/[name]-[contenthash:8].chunk.css'
    })
  )
  result.append(
    'Manifest',
    new WebpackAssetsManifest({
      entrypoints: true,
      writeToDisk: true,
      publicPath: config.publicPathWithoutCDN
    })
  )
  return result
}

const getExtensionsGlob = () => {
  const { extensions } = config
  return extensions.length === 1 ? `**/*${extensions[0]}` : `**/*{${extensions.join(',')}}`
}

const getEntryObject = () => {
  const result = new ConfigObject()
  const glob = getExtensionsGlob()
  const rootPath = join(config.source_path, config.source_entry_path)
  const paths = sync(join(rootPath, glob))
  paths.forEach((path) => {
    const namespace = relative(join(rootPath), dirname(path))
    const name = join(namespace, basename(path, extname(path)))
    let assetPaths = resolve(path)

    // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
    // Transforms the config object value to an array with all values under the same name
    let previousPaths = result.get(name)
    if (previousPaths) {
      previousPaths = Array.isArray(previousPaths) ? previousPaths : [previousPaths]
      previousPaths.push(assetPaths)
      assetPaths = previousPaths
    }

    result.set(name, assetPaths)
  })
  return result
}

const getModulePaths = () => {
  const result = new ConfigList()
  result.append('source', resolve(config.source_path))
  if (config.additional_paths) {
    config.additional_paths.forEach((path) => result.append(path, resolve(path)))
  }
  result.append('node_modules', 'node_modules')
  return result
}

const getBaseConfig = () => new ConfigObject({
  mode: 'production',
  output: {
    filename: 'js/[name]-[contenthash].js',
    chunkFilename: 'js/[name]-[contenthash].chunk.js',
    hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
    path: config.outputPath,
    publicPath: config.publicPath
  },

  resolve: {
    extensions: config.extensions,
    plugins: [PnpWebpackPlugin]
  },

  resolveLoader: {
    modules: ['node_modules'],
    plugins: [PnpWebpackPlugin.moduleLoader(module)]
  },

  node: {
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
})

module.exports = class Base {
  constructor() {
    this.loaders = getLoaderList()
    this.plugins = getPluginList()
    this.config = getBaseConfig()
    this.entry = getEntryObject()
    this.resolvedModules = getModulePaths()
  }

  splitChunks(callback = null) {
    let appConfig = {}
    const defaultConfig = {
      optimization: {
        // Split vendor and common chunks
        // https://twitter.com/wSokra/status/969633336732905474
        splitChunks: {
          chunks: 'all',
          name: false
        },
        // Separate runtime chunk to enable long term caching
        // https://twitter.com/wSokra/status/969679223278505985
        runtimeChunk: true
      }
    }

    if (callback) {
      appConfig = callback(defaultConfig)
      if (isNotObject(appConfig)) {
        throw new Error(`
          ${prettyPrint(appConfig)} is not a valid splitChunks configuration.
          See https://webpack.js.org/plugins/split-chunks-plugin/#configuration
        `)
      }
    }

    return this.config.merge(deepMerge(defaultConfig, appConfig))
  }

  toWebpackConfig() {
    return this.config.merge({
      entry: this.entry.toObject(),

      module: {
        strictExportPresence: true,
        rules: [{ parser: { requireEnsure: false } }, ...this.loaders.values()]
      },

      plugins: this.plugins.values(),

      resolve: {
        modules: this.resolvedModules.values()
      }
    })
  }
}
<commit_msg>Fix chunks cleanup (#2585)<commit_after>/* eslint global-require: 0 */
/* eslint import/no-dynamic-require: 0 */

const {
  basename, dirname, join, relative, resolve
} = require('path')
const { sync } = require('glob')
const extname = require('path-complete-extname')

const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const WebpackAssetsManifest = require('webpack-assets-manifest')
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
const PnpWebpackPlugin = require('pnp-webpack-plugin')

const { isNotObject, prettyPrint } = require('../utils/helpers')
const deepMerge = require('../utils/deep_merge')

const { ConfigList, ConfigObject } = require('../config_types')
const rules = require('../rules')
const config = require('../config')

const getLoaderList = () => {
  const result = new ConfigList()
  Object.keys(rules).forEach((key) => result.append(key, rules[key]))
  return result
}

const getPluginList = () => {
  const result = new ConfigList()
  result.append(
    'Environment',
    new webpack.EnvironmentPlugin(process.env)
  )
  result.append('CaseSensitivePaths', new CaseSensitivePathsPlugin())
  result.append(
    'MiniCssExtract',
    new MiniCssExtractPlugin({
      filename: 'css/[name]-[contenthash:8].css',
      chunkFilename: 'css/[name]-[contenthash:8].chunk.css'
    })
  )
  result.append(
    'Manifest',
    new WebpackAssetsManifest({
      entrypoints: true,
      writeToDisk: true,
      publicPath: config.publicPathWithoutCDN
    })
  )
  return result
}

const getExtensionsGlob = () => {
  const { extensions } = config
  return extensions.length === 1 ? `**/*${extensions[0]}` : `**/*{${extensions.join(',')}}`
}

const getEntryObject = () => {
  const result = new ConfigObject()
  const glob = getExtensionsGlob()
  const rootPath = join(config.source_path, config.source_entry_path)
  const paths = sync(join(rootPath, glob))
  paths.forEach((path) => {
    const namespace = relative(join(rootPath), dirname(path))
    const name = join(namespace, basename(path, extname(path)))
    let assetPaths = resolve(path)

    // Allows for multiple filetypes per entry (https://webpack.js.org/guides/entry-advanced/)
    // Transforms the config object value to an array with all values under the same name
    let previousPaths = result.get(name)
    if (previousPaths) {
      previousPaths = Array.isArray(previousPaths) ? previousPaths : [previousPaths]
      previousPaths.push(assetPaths)
      assetPaths = previousPaths
    }

    result.set(name, assetPaths)
  })
  return result
}

const getModulePaths = () => {
  const result = new ConfigList()
  result.append('source', resolve(config.source_path))
  if (config.additional_paths) {
    config.additional_paths.forEach((path) => result.append(path, resolve(path)))
  }
  result.append('node_modules', 'node_modules')
  return result
}

const getBaseConfig = () => new ConfigObject({
  mode: 'production',
  output: {
    filename: 'js/[name]-[contenthash].js',
    chunkFilename: 'js/[name]-[contenthash].chunk.js',
    hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
    path: config.outputPath,
    publicPath: config.publicPath
  },

  resolve: {
    extensions: config.extensions,
    plugins: [PnpWebpackPlugin]
  },

  resolveLoader: {
    modules: ['node_modules'],
    plugins: [PnpWebpackPlugin.moduleLoader(module)]
  },

  node: {
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
})

module.exports = class Base {
  constructor() {
    this.loaders = getLoaderList()
    this.plugins = getPluginList()
    this.config = getBaseConfig()
    this.entry = getEntryObject()
    this.resolvedModules = getModulePaths()
  }

  splitChunks(callback = null) {
    let appConfig = {}
    const defaultConfig = {
      optimization: {
        // Split vendor and common chunks
        // https://twitter.com/wSokra/status/969633336732905474
        splitChunks: {
          chunks: 'all',
          name: true
        },
        // Separate runtime chunk to enable long term caching
        // https://twitter.com/wSokra/status/969679223278505985
        runtimeChunk: true
      }
    }

    if (callback) {
      appConfig = callback(defaultConfig)
      if (isNotObject(appConfig)) {
        throw new Error(`
          ${prettyPrint(appConfig)} is not a valid splitChunks configuration.
          See https://webpack.js.org/plugins/split-chunks-plugin/#configuration
        `)
      }
    }

    return this.config.merge(deepMerge(defaultConfig, appConfig))
  }

  toWebpackConfig() {
    return this.config.merge({
      entry: this.entry.toObject(),

      module: {
        strictExportPresence: true,
        rules: [{ parser: { requireEnsure: false } }, ...this.loaders.values()]
      },

      plugins: this.plugins.values(),

      resolve: {
        modules: this.resolvedModules.values()
      }
    })
  }
}
<|endoftext|>