<commit_before>import * as d3 from 'd3';
import * as dc from 'dc'
import {crossfilter, units, geoChoroplethChart, bubbleChart, renderAll, redrawAll, filterAll, pieChart, barChart, dataCount, dataTable, pluck} from 'dc';
import * as colorbrewer from "colorbrewer";
import reductio from "reductio";
//we can call export at the top of the class declaration
export default class ThrashDashDC {

  constructor(el, props = {}) {
    //we initiate charts in constructor
    this.myCharts = ThrashDashDC.initCharts();
  }

  render() {
    //de-structure myCharts object
    let {SFHBubbleChart, SFQBubbleChart, SFCBubbleChart,
           QFBarChart, HFBarChart, crowdFactorChart,
           funFactorChart, yearChart, monthChart, dayChart} = this.myCharts;

    d3.json('data/thrashtown.json', (error, data) => {
      //format the data
      const surfData = this.formatData(data);
      const ttx = crossfilter(surfData);
      // build the x dimensions
      const xDims = this.buildXDimensions(ttx);
      //destructure the xDims object
      const {qualityFactorDim, hollowFactorDim, crowdFactorDim,
             funFactorDim, yearDim, monthDim, dayDim,
             stickDimQuality, stickDimCrowd, stickDimHollow} = xDims;
      //build the Y groups
      const yGroups = this.buildYGroups(ttx, xDims);
      //de-structure they yGroups object
      const {all, countPerQualityFactor, countPerHollowFactor, countPerCrowdFactor,
             countPerFunFactor, countPerYear, countPerMonth,countPerDay,
             stickGroup} = yGroups;

   SFQBubbleChart = this.buildBubbleChart(SFQBubbleChart, stickDimQuality, stickGroup, "quality", "fun");
   SFHBubbleChart = this.buildBubbleChart(SFHBubbleChart, stickDimHollow, stickGroup, "hollow", "fun");
   SFCBubbleChart = this.buildBubbleChart(SFCBubbleChart, stickDimCrowd, stickGroup, "crowd", "fun");
   QFBarChart = this.buildBarChart(QFBarChart, qualityFactorDim, countPerQualityFactor,"metric", "quality", "sessions");
   HFBarChart = this.buildBarChart(HFBarChart, hollowFactorDim, countPerHollowFactor,"metric", "hollow", "sessions");
/*      qualityFactorChart
        .width(300)
        .height(180)
        .dimension(qualityFactorDim)
        .group(countPerQualityFactor)
        .x(d3.scale.linear().domain([0,5.2]))
        .elasticY(true)
        .centerBar(true)
        .barPadding(5)
        .xAxisLabel('Quality Factor')
        .yAxisLabel('Sessions')
      qualityFactorChart.xAxis().tickValues([0,1,2,3,4,5]);

      hollowFactorChart
        .width(300)
        .height(180)
        .dimension(hollowFactorDim)
        .group(countPerHollowFactor)
        .x(d3.scale.linear().domain([0,5.2]))
        .elasticY(true)
        .centerBar(true)
        .barPadding(5)
        .xAxisLabel('Hollow Factor')
        .yAxisLabel('Sessions')
      hollowFactorChart.xAxis().tickValues([0,1,2,3,4,5]);*/

      crowdFactorChart
        .width(300)
        .height(180)
        .dimension(crowdFactorDim)
        .group(countPerCrowdFactor)
        .x(d3.scale.linear().domain([0,5.2]))
        .elasticY(true)
        .centerBar(true)
        .barPadding(5)
        .xAxisLabel('Crowd Factor')
        .yAxisLabel('Sessions')
      crowdFactorChart.xAxis().tickValues([0,1,2,3,4,5]);

      funFactorChart
        .width(300)
        .height(180)
        .dimension(funFactorDim)
        .group(countPerFunFactor)
        .x(d3.scale.linear().domain([0,5.2]))
        .elasticY(true)
        .centerBar(true)
        .barPadding(5)
        .xAxisLabel('Fun Factor')
        .yAxisLabel('Sessions')
      funFactorChart.xAxis().tickValues([0, 1, 2, 3, 4, 5]);

      yearChart
        .width(150)
        .height(150)
        .dimension(yearDim)
        .group(countPerYear)
        .innerRadius(20);

      monthChart
        .width(150)
        .height(150)
        .dimension(monthDim)
        .group(countPerMonth)
        .innerRadius(20)
        .ordering((d) => {
          const order = {
            'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4,
            'may': 5, 'jun': 6, 'jul': 7, 'aug': 8,
            'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12
          };
          return order[d.key];
        });

      dayChart
        .width(150)
        .height(150)
        .dimension(dayDim)
        .group(countPerDay)
        .innerRadius(20)
        .ordering((d) => {
          const order = {
            'mon': 0, 'tue': 1, 'wed': 2, 'thu': 3,
            'fri': 4, 'sat': 5, 'sun': 6
          }
          return order[d.key];
        });

      //draw the viz!
      renderAll();

    });
  }

  static initCharts() {
    const SFHBubbleChart = bubbleChart('#chart-bubble-stick-fun-hollow');
    const SFQBubbleChart = bubbleChart('#chart-bubble-stick-fun-quality');
    const SFCBubbleChart = bubbleChart('#chart-bubble-stick-fun-crowd');
    const QFBarChart = barChart('#chart-bar-quality-factor');
    const HFBarChart = barChart('#chart-bar-hollow-factor');
    const crowdFactorChart = barChart('#chart-bar-crowd-factor');
    const funFactorChart = barChart('#chart-bar-fun-factor');
    const yearChart = pieChart('#chart-ring-year');
    const monthChart = pieChart('#chart-ring-month');
    const dayChart = pieChart('#chart-ring-day');

    const myCharts = {SFHBubbleChart, SFQBubbleChart, SFCBubbleChart,
                      QFBarChart, HFBarChart, crowdFactorChart,
                      funFactorChart, yearChart, monthChart, dayChart};

    return myCharts;
  }

  resetChart(chartName) {

    let {SFHBubbleChart, SFQBubbleChart, SFCBubbleChart,
         QFBarChart, HFBarChart, crowdFactorChart,
         funFactorChart, yearChart, monthChart, dayChart} = this.myCharts;

    switch (chartName) {
      case "chart-ring-year":
        yearChart.filterAll();
        break;
      case "chart-ring-month":
        monthChart.filterAll();
        break;
      case "chart-ring-day":
        dayChart.filterAll();
        break;
      case "chart-bar-fun-factor":
        funFactorChart.filterAll();
        break;
      case "chart-bar-crowd-factor":
        crowdFactorChart.filterAll();
        break;
      case "chart-bar-hollow-factor":
        HFBarChart.filterAll();
        break;
      case "chart-bar-quality-factor":
        QFBarChart.filterAll();
        break;
      default:
        //Statements executed when none of the values match the value of the expression
        break;
    }

    redrawAll();
  }

buildBarChart(chart, dim, group, metric, x, y){
    //dc.barChart("#period-chart")
    chart
      .width(300)
      .height(180)
      .dimension(dim)
      .group(group)
      .x(d3.scale.linear().domain([0, 5.2]))
      .elasticY(true)
      .centerBar(true)
      .barPadding(5)
      .xAxisLabel(x)
      .yAxisLabel(y)
    return chart;
  }

  buildBubbleChart(chart, dim, group, x, y){
        //console.log(group.top(2));
      chart
        .width(400)
        .height(250)
        .transitionDuration(1500)
        .margins({top:10, right:50, bottom:30, left:40})
        .dimension(dim)
        .group(group)
        .ordinalColors(colorbrewer.Spectral[7])
        .colorAccessor((p) => {
          return p.key;
        })
        .keyAccessor((p) => {
          //return p.value.quality.avg;
          return p.value[x].avg;
        })
        .valueAccessor((p) => {
          return p.value[y].avg;
        })
        .radiusValueAccessor((p) => {
          return p.value.fun.count;
        })
        .maxBubbleRelativeSize(0.2)
        .x(d3.scale.linear().domain([0, 5]))
        .y(d3.scale.linear().domain([0, 5]))
        .r(d3.scale.linear().domain([0, 100]))
        .elasticY(false)
        .elasticX(false)
        .yAxisPadding(100)
        .xAxisPadding(500)
        .renderHorizontalGridLines(true)
        .renderVerticalGridLines(true)
        .xAxisLabel(x)
        .yAxisLabel(y)
        .yAxis().tickFormat(function (v) {
          return v + '%';
        });
    return chart;
  }

  formatData(data){

    const surfData = data;

    const fullDateFormat = d3.time.format("%a, %d %b %Y %X %Z");
    const yearFormat = d3.time.format('%Y');
    const monthFormat = d3.time.format('%b');
    const dayFormat = d3.time.format('%a');

    surfData.forEach(d=>{
      let dateObj  = new Date(d.sessionDate);
      d.sessionDateFormatted = fullDateFormat(dateObj);
      d.sessionYear = +yearFormat(dateObj);
      d.sessionMonth = monthFormat(dateObj);
      d.sessionDay = dayFormat(dateObj);
    });

    return surfData;
  }

  buildXDimensions(ttx){
    // create dimensions (x-axis values)
    const qualityFactorDim  = ttx.dimension(dc.pluck("waveQuality"));
    const hollowFactorDim  = ttx.dimension(dc.pluck("hollowness"));
    const crowdFactorDim  = ttx.dimension(dc.pluck("crowdedness"));
    const funFactorDim  = ttx.dimension(pluck("funFactor"));
    const yearDim  = ttx.dimension(pluck("sessionYear"));
    const monthDim  = ttx.dimension(pluck("sessionMonth"));
    const dayDim  = ttx.dimension(pluck("sessionDay"));
    const stickDimQuality  = ttx.dimension(pluck("board", (x,i) => {
      return x.name;
    }));
    const stickDimCrowd  = ttx.dimension(pluck("board", (x,i) => {
      return x.name;
    }));
    const stickDimHollow  = ttx.dimension(pluck("board", (x,i) => {
      return x.name;
    }));

    const xDims = { qualityFactorDim, hollowFactorDim, crowdFactorDim,
                    funFactorDim, yearDim, monthDim, dayDim,
                    stickDimQuality, stickDimCrowd, stickDimHollow };
    return xDims;

  }

  buildYGroups(ttx, xDims){

    const {qualityFactorDim, hollowFactorDim, crowdFactorDim,
           funFactorDim, yearDim, monthDim, dayDim,
           stickDimQuality, stickDimCrowd, stickDimHollow} = xDims;

    // create groups (y-axis values)
    const all = ttx.groupAll();
    const countPerQualityFactor = qualityFactorDim.group().reduceCount();
    const countPerHollowFactor = hollowFactorDim.group().reduceCount();
    const countPerCrowdFactor = crowdFactorDim.group().reduceCount();
    const countPerFunFactor = funFactorDim.group().reduceCount();
    const countPerYear = yearDim.group().reduceCount();
    const countPerMonth = monthDim.group().reduceCount();
    const countPerDay = dayDim.group().reduceCount();
    //map reduce functions
    let stickGroup = stickDimQuality.group();
    let bReducer = reductio();
    bReducer.value("quality").count(true).sum((d)=>{return d.waveQuality;}).avg(true);
    bReducer.value("fun").count(true).sum((d)=>{return d.funFactor}).avg(true);
    bReducer.value("crowd").count(true).sum((d)=>{return d.crowdedness}).avg(true);
    bReducer.value("hollow").count(true).sum((d)=>{return d.hollowness}).avg(true);
    bReducer(stickGroup);

    const yGroups = {all, countPerQualityFactor, countPerHollowFactor, countPerCrowdFactor,
                     countPerFunFactor, countPerYear, countPerMonth, countPerDay,
                     stickGroup};

    return yGroups;

  }

  //end of class
}
<commit_msg>bar chart refactor complete<commit_after>import * as d3 from 'd3';
import * as dc from 'dc'
import {crossfilter, units, geoChoroplethChart, bubbleChart, renderAll, redrawAll, filterAll, pieChart, barChart, dataCount, dataTable, pluck} from 'dc';
import * as colorbrewer from "colorbrewer";
import reductio from "reductio";
//we can call export at the top of the class declaration
export default class ThrashDashDC {

  constructor(el, props = {}) {
    //we initiate charts in constructor
    this.myCharts = ThrashDashDC.initCharts();
  }

  render() {
    //de-structure myCharts object
    let {SFHBubbleChart, SFQBubbleChart, SFCBubbleChart,
           QFBarChart, HFBarChart, CFBarChart,
           FFBarChart, yearChart, monthChart, dayChart} = this.myCharts;

    d3.json('data/thrashtown.json', (error, data) => {
      //format the data
      const surfData = this.formatData(data);
      const ttx = crossfilter(surfData);
      // build the x dimensions
      const xDims = this.buildXDimensions(ttx);
      //destructure the xDims object
      const {qualityFactorDim, hollowFactorDim, crowdFactorDim,
             funFactorDim, yearDim, monthDim, dayDim,
             stickDimQuality, stickDimCrowd, stickDimHollow} = xDims;
      //build the Y groups
      const yGroups = this.buildYGroups(ttx, xDims);
      //de-structure they yGroups object
      const {all, countPerQualityFactor, countPerHollowFactor, countPerCrowdFactor,
             countPerFunFactor, countPerYear, countPerMonth,countPerDay,
             stickGroup} = yGroups;

   SFQBubbleChart = this.buildBubbleChart(SFQBubbleChart, stickDimQuality, stickGroup, "quality", "fun");
   SFHBubbleChart = this.buildBubbleChart(SFHBubbleChart, stickDimHollow, stickGroup, "hollow", "fun");
   SFCBubbleChart = this.buildBubbleChart(SFCBubbleChart, stickDimCrowd, stickGroup, "crowd", "fun");
   QFBarChart = this.buildBarChart(QFBarChart, qualityFactorDim, countPerQualityFactor,"metric", "quality", "sessions");
   HFBarChart = this.buildBarChart(HFBarChart, hollowFactorDim, countPerHollowFactor,"metric", "hollow", "sessions");
   CFBarChart = this.buildBarChart(CFBarChart, crowdFactorDim, countPerCrowdFactor,"metric", "crowd", "sessions");
   FFBarChart = this.buildBarChart(FFBarChart, funFactorDim, countPerFunFactor,"metric", "fun", "sessions");

      yearChart
        .width(150)
        .height(150)
        .dimension(yearDim)
        .group(countPerYear)
        .innerRadius(20);

      monthChart
        .width(150)
        .height(150)
        .dimension(monthDim)
        .group(countPerMonth)
        .innerRadius(20)
        .ordering((d) => {
          const order = {
            'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4,
            'may': 5, 'jun': 6, 'jul': 7, 'aug': 8,
            'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12
          };
          return order[d.key];
        });

      dayChart
        .width(150)
        .height(150)
        .dimension(dayDim)
        .group(countPerDay)
        .innerRadius(20)
        .ordering((d) => {
          const order = {
            'mon': 0, 'tue': 1, 'wed': 2, 'thu': 3,
            'fri': 4, 'sat': 5, 'sun': 6
          }
          return order[d.key];
        });

      //draw the viz!
      renderAll();

    });
  }

  static initCharts() {
    const SFHBubbleChart = bubbleChart('#chart-bubble-stick-fun-hollow');
    const SFQBubbleChart = bubbleChart('#chart-bubble-stick-fun-quality');
    const SFCBubbleChart = bubbleChart('#chart-bubble-stick-fun-crowd');
    const QFBarChart = barChart('#chart-bar-quality-factor');
    const HFBarChart = barChart('#chart-bar-hollow-factor');
    const CFBarChart = barChart('#chart-bar-crowd-factor');
    const FFBarChart = barChart('#chart-bar-fun-factor');
    const yearChart = pieChart('#chart-ring-year');
    const monthChart = pieChart('#chart-ring-month');
    const dayChart = pieChart('#chart-ring-day');

    const myCharts = {SFHBubbleChart, SFQBubbleChart, SFCBubbleChart,
                      QFBarChart, HFBarChart, CFBarChart,
                      FFBarChart, yearChart, monthChart, dayChart};

    return myCharts;
  }

  resetChart(chartName) {

    let {SFHBubbleChart, SFQBubbleChart, SFCBubbleChart,
         QFBarChart, HFBarChart, CFBarChart,
         FFBarChart, yearChart, monthChart, dayChart} = this.myCharts;

    switch (chartName) {
      case "chart-ring-year":
        yearChart.filterAll();
        break;
      case "chart-ring-month":
        monthChart.filterAll();
        break;
      case "chart-ring-day":
        dayChart.filterAll();
        break;
      case "chart-bar-fun-factor":
        FFBarChart.filterAll();
        break;
      case "chart-bar-crowd-factor":
        CFBarChart.filterAll();
        break;
      case "chart-bar-hollow-factor":
        HFBarChart.filterAll();
        break;
      case "chart-bar-quality-factor":
        QFBarChart.filterAll();
        break;
      default:
        //Statements executed when none of the values match the value of the expression
        break;
    }

    redrawAll();
  }

buildBarChart(chart, dim, group, metric, x, y){
    //dc.barChart("#period-chart")
    chart
      .width(300)
      .height(180)
      .dimension(dim)
      .group(group)
      .x(d3.scale.linear().domain([0, 5.2]))
      .elasticY(true)
      .centerBar(true)
      .barPadding(5)
      .xAxisLabel(x)
      .yAxisLabel(y)

    chart.xAxis().tickValues([0, 1, 2, 3, 4, 5]);
    return chart;
  }

  buildBubbleChart(chart, dim, group, x, y){
        //console.log(group.top(2));
      chart
        .width(400)
        .height(250)
        .transitionDuration(1500)
        .margins({top:10, right:50, bottom:30, left:40})
        .dimension(dim)
        .group(group)
        .ordinalColors(colorbrewer.Spectral[7])
        .colorAccessor((p) => {
          return p.key;
        })
        .keyAccessor((p) => {
          //return p.value.quality.avg;
          return p.value[x].avg;
        })
        .valueAccessor((p) => {
          return p.value[y].avg;
        })
        .radiusValueAccessor((p) => {
          return p.value.fun.count;
        })
        .maxBubbleRelativeSize(0.2)
        .x(d3.scale.linear().domain([0, 5]))
        .y(d3.scale.linear().domain([0, 5]))
        .r(d3.scale.linear().domain([0, 100]))
        .elasticY(false)
        .elasticX(false)
        .yAxisPadding(100)
        .xAxisPadding(500)
        .renderHorizontalGridLines(true)
        .renderVerticalGridLines(true)
        .xAxisLabel(x)
        .yAxisLabel(y)
        .yAxis().tickFormat(function (v) {
          return v + '%';
        });
    return chart;
  }

  formatData(data){

    const surfData = data;

    const fullDateFormat = d3.time.format("%a, %d %b %Y %X %Z");
    const yearFormat = d3.time.format('%Y');
    const monthFormat = d3.time.format('%b');
    const dayFormat = d3.time.format('%a');

    surfData.forEach(d=>{
      let dateObj  = new Date(d.sessionDate);
      d.sessionDateFormatted = fullDateFormat(dateObj);
      d.sessionYear = +yearFormat(dateObj);
      d.sessionMonth = monthFormat(dateObj);
      d.sessionDay = dayFormat(dateObj);
    });

    return surfData;
  }

  buildXDimensions(ttx){
    // create dimensions (x-axis values)
    const qualityFactorDim  = ttx.dimension(dc.pluck("waveQuality"));
    const hollowFactorDim  = ttx.dimension(dc.pluck("hollowness"));
    const crowdFactorDim  = ttx.dimension(dc.pluck("crowdedness"));
    const funFactorDim  = ttx.dimension(pluck("funFactor"));
    const yearDim  = ttx.dimension(pluck("sessionYear"));
    const monthDim  = ttx.dimension(pluck("sessionMonth"));
    const dayDim  = ttx.dimension(pluck("sessionDay"));
    const stickDimQuality  = ttx.dimension(pluck("board", (x,i) => {
      return x.name;
    }));
    const stickDimCrowd  = ttx.dimension(pluck("board", (x,i) => {
      return x.name;
    }));
    const stickDimHollow  = ttx.dimension(pluck("board", (x,i) => {
      return x.name;
    }));

    const xDims = { qualityFactorDim, hollowFactorDim, crowdFactorDim,
                    funFactorDim, yearDim, monthDim, dayDim,
                    stickDimQuality, stickDimCrowd, stickDimHollow };
    return xDims;

  }

  buildYGroups(ttx, xDims){

    const {qualityFactorDim, hollowFactorDim, crowdFactorDim,
           funFactorDim, yearDim, monthDim, dayDim,
           stickDimQuality, stickDimCrowd, stickDimHollow} = xDims;

    // create groups (y-axis values)
    const all = ttx.groupAll();
    const countPerQualityFactor = qualityFactorDim.group().reduceCount();
    const countPerHollowFactor = hollowFactorDim.group().reduceCount();
    const countPerCrowdFactor = crowdFactorDim.group().reduceCount();
    const countPerFunFactor = funFactorDim.group().reduceCount();
    const countPerYear = yearDim.group().reduceCount();
    const countPerMonth = monthDim.group().reduceCount();
    const countPerDay = dayDim.group().reduceCount();
    //map reduce functions
    let stickGroup = stickDimQuality.group();
    let bReducer = reductio();
    bReducer.value("quality").count(true).sum((d)=>{return d.waveQuality;}).avg(true);
    bReducer.value("fun").count(true).sum((d)=>{return d.funFactor}).avg(true);
    bReducer.value("crowd").count(true).sum((d)=>{return d.crowdedness}).avg(true);
    bReducer.value("hollow").count(true).sum((d)=>{return d.hollowness}).avg(true);
    bReducer(stickGroup);

    const yGroups = {all, countPerQualityFactor, countPerHollowFactor, countPerCrowdFactor,
                     countPerFunFactor, countPerYear, countPerMonth, countPerDay,
                     stickGroup};

    return yGroups;

  }

  //end of class
}
<|endoftext|>


<commit_before>define(
    [
        'easelbone'
    ],
    function (
        easelbone
    ) {
        "use strict";

        var img = new Image();
        img.crossOrigin = 'anonymous';

        img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAWCAYAAAA1vze2AAAABmJLR0QA/wD/AP+gvaeT" +
            "AAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH3wMRCycoY5y7DgAAAeBJREFUSMel1j9sTlEYBvD3fv2DIqmmmmjTBSXV" +
            "kYSBhAixWNRmMYvBgMZQSUeLQWIw2hqLWIRBYpCIQYcyYDBJNAQpBk21P8u5cdzcfv1835Pc3JznOed9zn3f95zciCbAAbzE" +
            "Ik5VtI04jxmMRzvAKD76i1VszvSZTFvESDsmk1jxLyYz/UtFu7pWrEYTn9EafUcyGIiIgYo23o5Jdw23kt79NVrR1AQNbEEe" +
            "+F0WtMSLiIiiKN5HxGqdluL1oB89JdGFabzGLWxKfB9ms5zfqdTsYqbNoT+LN5tqdq+cfLrSQUcrOxrGCLoqJg1sxxg2ZPyZ" +
            "SsNcCTyvdMlUdABMpc2W+NyIiP2VecMtBjuMEzVSX2U82B0RSxHRk5H5gTsbEbcjYig1wpuI2BoRx7I5cxFxqCiK5URtq3Sa" +
            "wINKui6nxfvwU2u4npneqGjzkQr3LRFPMZil40eLJnfLxsAQHuErHpfx1sr5Xnxq0WS6Wf2anfhzKb/r4XeqVcvt14sL//EF" +
            "JZ6Uh3g9gzF80D7u4yQm1rzU8DYi9kRnWE333WBRFN/rarIQnaMREb/SU5uu3VjWOS6haFaX41iqWbjQosE8eltpgAk8TKf9" +
            "FXYl/kgawzMcTPxOXMPN/B8gxx+XbHMxap3gAwAAAABJRU5ErkJggg==";

        var step = 0;

        var pawsize = {
            'width': 20,
            'height': 20
        };

        var limits = {
            'x': {
                'start': 0,
                'end': 100
            },
            'y': {
                'start': 0,
                'end': 100
            }
        };

        var position = {
            'x': limits.x.end / 2,
            'y': limits.y.end / 2
        };

        var dx = Math.random();
        var dy = 1 - dx;

        var speed = 10;

        dx *= speed;
        dy *= speed;

        var points = [];
        var flipper = false;

        return easelbone.Views.Base.extend({

            initialize: function(options) {
                this.gameVersion = options.gameVersion;
                this.dRotation = 0.0;
            },

            render: function() {

                limits = {
                    'x': {
                        'start': 0,
                        'end': this.el.stage.canvas.width
                    },
                    'y': {
                        'start': 0,
                        'end': this.el.stage.canvas.height
                    }
                };

                this.loadingText = new createjs.Text('Loading', '15px monospace', '#ffffff');
                this.loadingText.textAlign = 'center';
                this.loadingText.lineHeight = 20;
                this.el.addChild(this.loadingText);

                this.versionText = new createjs.Text('v' + this.gameVersion, '12px monospace', '#ffffff');
                this.el.addChild(this.versionText);

                this.versionText.cache(-100, 0, 100, 200);
                this.loadingText.cache(-100, 0, 100, 200);

                this.el.setBounds(0, 0, this.el.stage.canvas.width, this.el.stage.canvas.height);
                this.updatePositions();

                position = {
                    x: Math.random() * limits.x.end,
                    y: Math.random() * limits.y.end
                };

                /*
                this.versionText = new createjs.Text('v1.0.0', '12px monospace', '#ffffff');
                this.el.addChild(this.versionText);*/
            },

            tick: function() {
                this.updatePositions();

                position.x += dx;
                position.y += dy;

                if (position.x < limits.x.start) {
                    dx *= -1;
                }

                if (position.x > limits.x.end) {
                    dx *= -1;
                }

                if (position.y < limits.y.start) {
                    dy *= -1;
                }

                if (position.y > limits.y.end) {
                    dy *= -1;
                }

                step ++;
                if (step % 6 === 0) {
                    this.addPaw();
                }

                for (var i = 0; i < points.length; i++) {
                    points[i].alpha -= (1 / 40);
                }

                var tmppoints = [];
                for (i = 0; i < points.length; i++) {
                    if (points[i].alpha > 0) {
                        tmppoints.push(points[i]);
                    }
                }
                points = tmppoints;

                return true;
            },

            updatePositions: function() {
                this.loadingText.x = (this.el.getBounds().width / 2) - 25;
                this.loadingText.y = this.el.getBounds().height / 2;

                this.versionText.x = this.el.getBounds().width - 60;
                this.versionText.y = this.el.getBounds().height - 20;
            },

            stop: function() {

            },

            start: function() {

            },

            addPaw : function () {

                flipper = !flipper;

                var ox = 10;
                if (flipper) {
                    ox *= -1;
                }

                /*
                var g = new createjs.Graphics();
                g.setStrokeStyle(1);
                g.beginStroke("#000000");
                g.beginFill("yellow");
                g.drawCircle(0,0,3);

                var shape = new createjs.Shape(g);
                shape.x = position.x;
                shape.y = position.y;
                this.el.addChild(shape);
                 */

                var pawImage = new createjs.Bitmap(img);
                var atan = Math.atan2(dy, dx);

                pawImage.regX = pawsize.width / 2;
                pawImage.regY = pawsize.height / 2;

                pawImage.x = position.x + (Math.cos(atan + Math.PI / 2) * ox);
                pawImage.y = position.y + (Math.sin(atan + Math.PI / 2) * ox);

                pawImage.scaleX = pawsize.width / img.width;
                pawImage.scaleY = pawsize.height / img.height;

                pawImage.rotation = (atan + (Math.PI / 2)) * (180 / Math.PI);

                this.el.addChild(pawImage);
                points.push(pawImage);
            },

            /**
             * @param percentage Between 0 and 1
             */
            setProgress: function (percentage) {
                percentage = Math.floor(percentage);

                this.loadingText.text = 'Loading\n' + percentage + '%';
                this.loadingText.cache(-100, -100, 200, 200);
            },

        });
    }
);
<commit_msg>Move loadingview to views.<commit_after>define(
    [
        'CatLab/Easelbone/Views/Base'
    ],
    function (
        Base
    ) {
        "use strict";

        var img = new Image();
        img.crossOrigin = 'anonymous';

        img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAWCAYAAAA1vze2AAAABmJLR0QA/wD/AP+gvaeT" +
            "AAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH3wMRCycoY5y7DgAAAeBJREFUSMel1j9sTlEYBvD3fv2DIqmmmmjTBSXV" +
            "kYSBhAixWNRmMYvBgMZQSUeLQWIw2hqLWIRBYpCIQYcyYDBJNAQpBk21P8u5cdzcfv1835Pc3JznOed9zn3f95zciCbAAbzE" +
            "Ik5VtI04jxmMRzvAKD76i1VszvSZTFvESDsmk1jxLyYz/UtFu7pWrEYTn9EafUcyGIiIgYo23o5Jdw23kt79NVrR1AQNbEEe" +
            "+F0WtMSLiIiiKN5HxGqdluL1oB89JdGFabzGLWxKfB9ms5zfqdTsYqbNoT+LN5tqdq+cfLrSQUcrOxrGCLoqJg1sxxg2ZPyZ" +
            "SsNcCTyvdMlUdABMpc2W+NyIiP2VecMtBjuMEzVSX2U82B0RSxHRk5H5gTsbEbcjYig1wpuI2BoRx7I5cxFxqCiK5URtq3Sa" +
            "wINKui6nxfvwU2u4npneqGjzkQr3LRFPMZil40eLJnfLxsAQHuErHpfx1sr5Xnxq0WS6Wf2anfhzKb/r4XeqVcvt14sL//EF" +
            "JZ6Uh3g9gzF80D7u4yQm1rzU8DYi9kRnWE333WBRFN/rarIQnaMREb/SU5uu3VjWOS6haFaX41iqWbjQosE8eltpgAk8TKf9" +
            "FXYl/kgawzMcTPxOXMPN/B8gxx+XbHMxap3gAwAAAABJRU5ErkJggg==";

        var step = 0;

        var pawsize = {
            'width': 20,
            'height': 20
        };

        var limits = {
            'x': {
                'start': 0,
                'end': 100
            },
            'y': {
                'start': 0,
                'end': 100
            }
        };

        var position = {
            'x': limits.x.end / 2,
            'y': limits.y.end / 2
        };

        var dx = Math.random();
        var dy = 1 - dx;

        var speed = 10;

        dx *= speed;
        dy *= speed;

        var points = [];
        var flipper = false;

        return Base.extend({

            initialize: function(options) {
                this.gameVersion = options.gameVersion;
                this.dRotation = 0.0;
            },

            render: function() {

                limits = {
                    'x': {
                        'start': 0,
                        'end': this.el.stage.canvas.width
                    },
                    'y': {
                        'start': 0,
                        'end': this.el.stage.canvas.height
                    }
                };

                this.loadingText = new createjs.Text('Loading', '15px monospace', '#ffffff');
                this.loadingText.textAlign = 'center';
                this.loadingText.lineHeight = 20;
                this.el.addChild(this.loadingText);

                this.versionText = new createjs.Text('v' + this.gameVersion, '12px monospace', '#ffffff');
                this.el.addChild(this.versionText);

                this.versionText.cache(-100, 0, 100, 200);
                this.loadingText.cache(-100, 0, 100, 200);

                this.el.setBounds(0, 0, this.el.stage.canvas.width, this.el.stage.canvas.height);
                this.updatePositions();

                position = {
                    x: Math.random() * limits.x.end,
                    y: Math.random() * limits.y.end
                };

                /*
                this.versionText = new createjs.Text('v1.0.0', '12px monospace', '#ffffff');
                this.el.addChild(this.versionText);*/
            },

            tick: function() {
                this.updatePositions();

                position.x += dx;
                position.y += dy;

                if (position.x < limits.x.start) {
                    dx *= -1;
                }

                if (position.x > limits.x.end) {
                    dx *= -1;
                }

                if (position.y < limits.y.start) {
                    dy *= -1;
                }

                if (position.y > limits.y.end) {
                    dy *= -1;
                }

                step ++;
                if (step % 6 === 0) {
                    this.addPaw();
                }

                for (var i = 0; i < points.length; i++) {
                    points[i].alpha -= (1 / 40);
                }

                var tmppoints = [];
                for (i = 0; i < points.length; i++) {
                    if (points[i].alpha > 0) {
                        tmppoints.push(points[i]);
                    }
                }
                points = tmppoints;

                return true;
            },

            updatePositions: function() {
                this.loadingText.x = (this.el.getBounds().width / 2) - 25;
                this.loadingText.y = this.el.getBounds().height / 2;

                this.versionText.x = this.el.getBounds().width - 60;
                this.versionText.y = this.el.getBounds().height - 20;
            },

            stop: function() {

            },

            start: function() {

            },

            addPaw : function () {

                flipper = !flipper;

                var ox = 10;
                if (flipper) {
                    ox *= -1;
                }

                /*
                var g = new createjs.Graphics();
                g.setStrokeStyle(1);
                g.beginStroke("#000000");
                g.beginFill("yellow");
                g.drawCircle(0,0,3);

                var shape = new createjs.Shape(g);
                shape.x = position.x;
                shape.y = position.y;
                this.el.addChild(shape);
                 */

                var pawImage = new createjs.Bitmap(img);
                var atan = Math.atan2(dy, dx);

                pawImage.regX = pawsize.width / 2;
                pawImage.regY = pawsize.height / 2;

                pawImage.x = position.x + (Math.cos(atan + Math.PI / 2) * ox);
                pawImage.y = position.y + (Math.sin(atan + Math.PI / 2) * ox);

                pawImage.scaleX = pawsize.width / img.width;
                pawImage.scaleY = pawsize.height / img.height;

                pawImage.rotation = (atan + (Math.PI / 2)) * (180 / Math.PI);

                this.el.addChild(pawImage);
                points.push(pawImage);
            },

            /**
             * @param percentage Between 0 and 1
             */
            setProgress: function (percentage) {
                percentage = Math.floor(percentage);

                this.loadingText.text = 'Loading\n' + percentage + '%';
                this.loadingText.cache(-100, -100, 200, 200);
            },

        });
    }
);
<|endoftext|>


<commit_before>/**
 * A possible component handler interface using the revealing module design
 * pattern.
 * @author Jason Mayes.
 */
var componentHandler = function() {
  'use strict';

  var registeredComponents_ = [];
  var createdComponents_ = [];

  /**
   * Searches registered components for a class we are interested in using.
   * Optionally replaces a match with passed object if specified.
   * @param {string} name The name of a class we want to use.
   * @param {object} opt_replace Optional object to replace match with.
   * @return {Object | false}
   * @private
   */
  function findRegisteredClass_(name, opt_replace) {
    for (var i = 0; i < registeredComponents_.length; i++) {
      if (registeredComponents_[i].className === name) {
        if (opt_replace !== undefined) {
          registeredComponents_[i] = opt_replace;
        }
        return registeredComponents_[i];
      }
    }
    return false;
  }

  /**
   * Searches existing DOM for elements of our component type and upgrades them
   * if they have not already been upgraded.
   * @param {string} jsClass the programatic name of the element class we need
   * to create a new instance of.
   * @param {string} cssClass the name of the CSS class elements of this type
   * will have.
   */
  function upgradeDomInternal(jsClass, cssClass) {
    if (cssClass === undefined) {
      var registeredClass = findRegisteredClass_(jsClass);
      if (registeredClass) {
        cssClass = registeredClass.cssClass;
      }
    }

    var elements = document.querySelectorAll('.' + cssClass);
    for (var n = 0; n < elements.length; n++) {
      upgradeElementInternal(elements[n], jsClass);
    }
  }

  /**
   * Upgrades a specific element rather than all in the DOM.
   * @param {HTMLElement} element The element we wish to upgrade.
   * @param {string} jsClass The name of the class we want to upgrade
   * the element to.
   */
  function upgradeElementInternal(element, jsClass) {
    // Only upgrade elements that have not already been upgraded.
    if (element.getAttribute('data-upgraded') === null) {
      // Upgrade element.
      element.setAttribute('data-upgraded', '');
      var registeredClass = findRegisteredClass_(jsClass);
      if (registeredClass) {
        createdComponents_.push(new registeredClass.classConstructor(element));
      } else {
        // If component creator forgot to register, try and see if
        // it is in global scope.
        createdComponents_.push(new window[jsClass](element));
      }
    }
  }

  /**
   * Registers a class for future use and attempts to upgrade existing DOM.
   * @param {object} config An object containting:
   * {constructor: Constructor, classAsString: string, cssClass: string}
   */
  function registerInternal(config) {
    var newConfig = {
      'classConstructor': config.constructor,
      'className': config.classAsString,
      'cssClass': config.cssClass
    };

    var found = findRegisteredClass_(config.classAsString, newConfig);

    if (!found) {
      registeredComponents_.push(newConfig);
    }

    upgradeDomInternal(config.classAsString);
  }

  // Now return the functions that should be made public with their publicly
  // facing names...
  return {
    upgradeDom: upgradeDomInternal,
    upgradeElement: upgradeElementInternal,
    register: registerInternal
  };
}();<commit_msg>Lowercase object in return comment.<commit_after>/**
 * A possible component handler interface using the revealing module design
 * pattern.
 * @author Jason Mayes.
 */
var componentHandler = function() {
  'use strict';

  var registeredComponents_ = [];
  var createdComponents_ = [];

  /**
   * Searches registered components for a class we are interested in using.
   * Optionally replaces a match with passed object if specified.
   * @param {string} name The name of a class we want to use.
   * @param {object} opt_replace Optional object to replace match with.
   * @return {object | false}
   * @private
   */
  function findRegisteredClass_(name, opt_replace) {
    for (var i = 0; i < registeredComponents_.length; i++) {
      if (registeredComponents_[i].className === name) {
        if (opt_replace !== undefined) {
          registeredComponents_[i] = opt_replace;
        }
        return registeredComponents_[i];
      }
    }
    return false;
  }

  /**
   * Searches existing DOM for elements of our component type and upgrades them
   * if they have not already been upgraded.
   * @param {string} jsClass the programatic name of the element class we need
   * to create a new instance of.
   * @param {string} cssClass the name of the CSS class elements of this type
   * will have.
   */
  function upgradeDomInternal(jsClass, cssClass) {
    if (cssClass === undefined) {
      var registeredClass = findRegisteredClass_(jsClass);
      if (registeredClass) {
        cssClass = registeredClass.cssClass;
      }
    }

    var elements = document.querySelectorAll('.' + cssClass);
    for (var n = 0; n < elements.length; n++) {
      upgradeElementInternal(elements[n], jsClass);
    }
  }

  /**
   * Upgrades a specific element rather than all in the DOM.
   * @param {HTMLElement} element The element we wish to upgrade.
   * @param {string} jsClass The name of the class we want to upgrade
   * the element to.
   */
  function upgradeElementInternal(element, jsClass) {
    // Only upgrade elements that have not already been upgraded.
    if (element.getAttribute('data-upgraded') === null) {
      // Upgrade element.
      element.setAttribute('data-upgraded', '');
      var registeredClass = findRegisteredClass_(jsClass);
      if (registeredClass) {
        createdComponents_.push(new registeredClass.classConstructor(element));
      } else {
        // If component creator forgot to register, try and see if
        // it is in global scope.
        createdComponents_.push(new window[jsClass](element));
      }
    }
  }

  /**
   * Registers a class for future use and attempts to upgrade existing DOM.
   * @param {object} config An object containting:
   * {constructor: Constructor, classAsString: string, cssClass: string}
   */
  function registerInternal(config) {
    var newConfig = {
      'classConstructor': config.constructor,
      'className': config.classAsString,
      'cssClass': config.cssClass
    };

    var found = findRegisteredClass_(config.classAsString, newConfig);

    if (!found) {
      registeredComponents_.push(newConfig);
    }

    upgradeDomInternal(config.classAsString);
  }

  // Now return the functions that should be made public with their publicly
  // facing names...
  return {
    upgradeDom: upgradeDomInternal,
    upgradeElement: upgradeElementInternal,
    register: registerInternal
  };
}();<|endoftext|>


<commit_before>var args = arguments[0] || {};
if(args !== {})
	init(args);
function init(o){
	//dynamic exprs in tss files no longer accepted
	if(OS_IOS){
		$.imgMain.top = 7;//0
		$.table.top = 0;//-15
	}
	$.title.text = o.title || "";
	$.main.text = o.main || "";
	$.licence.text = o.licence || "";
	if(o.thanksTo || $.thanksTo.text != ""){
		$.thanksTitle.text = o.thanksTitle || ($.thanksTitle.text == ""? "Thanks to:" : $.thanksTitle.text);
	}else{
		$.mainView.remove($.thanksTo);
	}
	if(!o.imgTitle){
		$.head.remove($.thanksTo);
	}else{
		$.imgTitle.image = o.imgTitle || $.imgTitle.image;
	}
	if(!o.imgMain){
		$.mainView.remove($.imgMain);
	}else{
		$.imgMain.image = o.imgMain || $.imgMain.image;
	}
	if(!o.imgWin){
		$.win.backgroundImage = null;
	}else{
		$.win.backgroundImage = o.imgWin || (OS_ANDROID?$.win.backgroundImage.toLowerCase():$.win.backgroundImage);
	}
	if(o.thanksTo){
		var data = [];
		_.each(o.thanksTo.split(','), function(pair) {
			var row = Alloy.createWidget('es.kabomi.about', 'rows', {
				name: pair.split('|')[0],
				contrib: pair.split('|')[1]
			}).getView();
			data.push(row);
		});
		$.table.setData(data);
		$.thanksTo.hide();
	}

	if(OS_ANDROID){
		$.win.addEventListener('android:back', function(){
			$.win.close();
		});
	}
};
exports.init = init;
exports.show = function(){
	if(Alloy.CFG.navgroup){
		Alloy.CFG.navgroup.open($.win);
	}else{
		$.win.open();
	}
};
exports.hide = function(){
	$.win.close();
};
exports.setPath = function(o, path){
	switch(o){
		case "main":
			$.imgMain.image = WPATH(path);
			break;
		case "logo":
			$.imgTitle.image = WPATH(path);
			break;
		case "win":
			$.win.backgroundImage = WPATH(path);
			break;
	}
};
<commit_msg>Refactor<commit_after>var args = arguments[0] || {};
if(args !== {})
	init(args);
function init(o){
	//dynamic exprs in tss files no longer accepted
	if(OS_IOS){
		$.imgMain.top = 7;//0
		$.table.top = 0;//-15
	}
	$.title.text = o.title || "";
	$.main.text = o.main || "";
	$.licence.text = o.licence || "";
	if(o.thanksTo || $.thanksTo.text != ""){
		$.thanksTitle.text = o.thanksTitle || ($.thanksTitle.text == ""? "Thanks to:" : $.thanksTitle.text);
	}else{
		$.mainView.remove($.thanksTo);
	}
	if(!o.imgTitle){
		$.head.remove($.thanksTo);
	}else{
		$.imgTitle.image = o.imgTitle || $.imgTitle.image;
	}
	if(!o.imgMain){
		$.mainView.remove($.imgMain);
	}else{
		$.imgMain.image = o.imgMain || $.imgMain.image;
	}
	if(!o.imgWin){
		$.win.backgroundImage = null;
	}else{
		$.win.backgroundImage = o.imgWin || (OS_ANDROID?$.win.backgroundImage.toLowerCase():$.win.backgroundImage);
	}
	if(o.thanksTo){
		var data = [];
		_.each(o.thanksTo.split(','), function(pair) {
			var row = Alloy.createWidget('es.kabomi.about', 'rows', {
				name: pair.split('|')[0],
				contrib: pair.split('|')[1]
			}).getView();
			data.push(row);
		});
		$.table.setData(data);
		$.thanksTo.hide();
	}

	if(OS_ANDROID){
		$.win.addEventListener('android:back', function(){
			$.win.close();
		});
	}
};

function show(){
	if(Alloy.CFG.navgroup){
		Alloy.CFG.navgroup.open($.win);
	}else{
		$.win.open();
	}
};
function hide(){
	$.win.close();
};
function setPath(o, path){
	switch(o){
		case "main":
			$.imgMain.image = WPATH(path);
			break;
		case "logo":
			$.imgTitle.image = WPATH(path);
			break;
		case "win":
			$.win.backgroundImage = WPATH(path);
			break;
	}
};

exports.init = init;
exports.show = show;
exports.hide = hide;
exports.setPath = setPath;
<|endoftext|>


<commit_before>// ==========================================================================
//                            DG.BinnedAxisView
//
//  Author:   William Finzer
//
//  Copyright (c) 2019 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

sc_require('components/graph/axes/axis_view');

/** @class  DG.BinnedAxisView - The view for a graph axis that displays numeric bins.

 @extends DG.AxisView
 */
DG.BinnedAxisView = DG.AxisView.extend( (function() {
  var kTickLength = 4,
      kAxisGap = 2;

  return {
    /** @scope DG.BinnedAxisView.prototype */

    /**
     Number of pixels required from the axis line to the edge of the graph view
     @property { Number }
     */
    desiredExtent: function() {
      var kWidthFudge = 5;
      return sc_super() + kTickLength + kAxisGap + kWidthFudge + this.get('maxLabelExtent');
    }.property('maxLabelExtent'),

    /**
     * When we are the "other" axis, our partner needs to know how much to offset pixelMin.
     * For me, it's the same as desiredExtent
     * @property {Number}
     */
    pixelMinOffset: function() {
      return this.get('desiredExtent');
    }.property('desiredExtent'),

    /**
     It's not clear whether this is a numeric axis or not
     @property { Boolean }
     */
    isNumeric: true,

    /**
     * @property {Boolean}
     */
    centering: true,

    /**
     @property {Number} Each time we draw the axis, we set this property to the maximum width
     of the label strings. Note that this will change depending not only on the length of the
     strings but on the rotation of the labels.
     */
    maxLabelExtent: 0,

    allowCellBoundaries: false,

    numberOfBins: function() {
      return this.getPath('model.binnedPlotModel.totalNumberOfBins');
    }.property(),
    numberOfBinsDidChange: function() {
      this.notifyPropertyChange( 'numberOfBins');
    }.observes('model.binnedPlotModel.totalNumberOfBins'),

    /**
     * @return { Number} in pixels
     */
    binWidth: function() {
      var tNumBins = this.get('numberOfBins');

      return Math.abs(this.get('pixelMax') - this.get('pixelMin')) / tNumBins;
    }.property('numberOfBins'),

    labelSpecs: null,

    /**
     *
     * @param iBinNum {Number}
     * @return {Number} screen coordinate of center of bin
     */
    binToCoordinate: function( iBinNum) {
      var tOffset = (iBinNum + 0.5) * this.get('binWidth');
      if (this.get('orientation') === DG.GraphTypes.EOrientation.kVertical)
        tOffset = -tOffset;
      return this.get('pixelMin') + tOffset;
    },

    /**
     *
     * @param iWorldValue
     * @return {Number} in screen coordinates
     */
    dataToCoordinate: function( iWorldValue) {
      return this.binToCoordinate( Math.floor( (iWorldValue - this.getPath( 'model.binnedPlotModel.alignment')) /
        this.getPath('model.binnedPlotModel.width')));
    },

    binnedPlotModelWidthOrAlignmentDidChange: function() {
      this.displayDidChange();
    }.observes('model.binnedPlotModel.width', 'model.binnedPlotModel.alignment'),

    /**
     Since I'm a leaf class I implement doDraw.
     */
    doDraw: function doDraw() {

      // We can get stuck if we have height or width of zero
      var tFrame = this.get('frame');
      if( !tFrame || (tFrame.height === 0 || tFrame.width === 0))
        return;

      var this_ = this,
          kHorizontalOrientations = [DG.GraphTypes.EOrientation.kHorizontal, DG.GraphTypes.EOrientation.kTop],
          tModel = this.get('model'),
          tNumBins = tModel.get('numberOfBins'),
          tBaseline = this_.get('axisLineCoordinate'),
          tOrientation = this.get('orientation'),
          tIsHorizontal = kHorizontalOrientations.indexOf( tOrientation) >= 0,
          tRotation = tIsHorizontal ? 0 : -90, // default to parallel to axis
          tMaxHeight = DG.RenderingUtilities.kDefaultFontHeight,  // So there will be a default extent
          tCentering = this.get('centering'),
          tTickOffset = tCentering ? 0 : this.get('binWidth') / 2,
          tAnchor = tCentering ? 'middle' : 'start',
          tMaxWidth = tMaxHeight,
          tLabels = this.getPath('model.binLabels'),
          tLabelSpecs = this.get('labelSpecs') || [],
          tCollision = false,
          kCollisionPadding = 5,
          tPrevLabelEnd;

      function measureOneBin( iBinLabelAndTitle, iBinNum) {
        var tCoord = this_.binToCoordinate(iBinNum);
        if( !isFinite( tCoord)) {
          return;
        }
        var tTextElement;
        if( !tLabelSpecs[iBinNum]) {
          tTextElement = this_.get('paper').text(0, 0, iBinLabelAndTitle.label)
              .addClass('dg-axis-tick-label')
              .addClass('dg-binned-axis-label');
        }
        else {
          tTextElement = tLabelSpecs[ iBinNum].element;
          tTextElement.attr('text', iBinLabelAndTitle.label);
        }
        tTextElement.attr('title', iBinLabelAndTitle.title);
        var tTextExtent = DG.RenderingUtilities.getExtentForTextElement(
                          tTextElement, DG.RenderingUtilities.kDefaultFontHeight, true /* compute with no transform */);

        tTextElement.binNum = iBinNum;
        tLabelSpecs[iBinNum] = { element: tTextElement, coord: tCoord,
                      height: tTextExtent.height, width: tTextExtent.width };

        tMaxHeight = Math.max( tMaxHeight, tTextExtent.height);
        tMaxWidth = Math.max( tMaxWidth, tTextExtent.width);
        if(SC.none( tPrevLabelEnd)) {
          tCollision = tTextExtent.width > this_.get('binWidth');
          tPrevLabelEnd = tIsHorizontal ? tCoord + tTextExtent.width / 2 : tCoord - tTextExtent.width / 2;
        }
        else if( tIsHorizontal) {
          tCollision = tCollision || (tCoord - tTextExtent.width / 2 < tPrevLabelEnd + kCollisionPadding);
          tPrevLabelEnd = (tCoord + tTextExtent.width / 2);
        }
        else {  // vertical
          tCollision = tCollision || (tCoord + tTextExtent.width / 2 > tPrevLabelEnd - kCollisionPadding);
          tPrevLabelEnd = (tCoord - tTextExtent.width / 2);
        }
      } // measureOneBin

      // iLabelSpec has form { element: {Raphael element}, coord: {Number}, height: {Number}, width: {Number} }
      function drawOneCell( iLabelSpec, iIndex) {
        var tCoord = iLabelSpec.coord,
            tLabelX, tLabelY;
        switch( this_.get('orientation')) {
          case DG.GraphTypes.EOrientation.kVertical:
            this_._elementsToClear.push(
              this_.get('paper').line( tBaseline, tCoord + tTickOffset, tBaseline - kTickLength, tCoord + tTickOffset)
                .attr( { stroke: DG.PlotUtilities.kAxisColor }));
            tLabelX = tBaseline - kTickLength - kAxisGap - iLabelSpec.height / 3;
            tLabelY = tCoord + tTickOffset - ((iIndex === 0 && !tCentering) ? iLabelSpec.height / 2 : 0);
            if( tRotation === 0) {
              tAnchor = 'end';
              if( iLabelSpec.width > tLabelX && tLabelX > 10) {
                DG.RenderingUtilities.elideToFit( iLabelSpec.element, tLabelX);
              }
            }
            break;

          case DG.GraphTypes.EOrientation.kHorizontal:
            this_._elementsToClear.push(
              this_.get('paper').line( tCoord - tTickOffset, tBaseline, tCoord - tTickOffset, tBaseline + kTickLength)
                .attr( { stroke: DG.PlotUtilities.kAxisColor }));
            tLabelX = tCoord - tTickOffset + 1;
            tLabelY = tBaseline + kTickLength + kAxisGap + iLabelSpec.height / 3;
            if( tRotation === -90) {
              tAnchor = 'end';
              if( iIndex === 0 && !tCentering)
                tLabelX += iLabelSpec.height / 3;
              if( iLabelSpec.width > tFrame.height - tLabelY && tFrame.height - tLabelY > 10)
                DG.RenderingUtilities.elideToFit( iLabelSpec.element, tFrame.height - tLabelY);
            }
            break;
        }
        iLabelSpec.element.attr( { x: tLabelX, y: tLabelY, 'text-anchor': tAnchor });
        DG.RenderingUtilities.rotateText( iLabelSpec.element, tRotation, tLabelX, tLabelY);
      } // drawOneCell

      //==========Main body of doDraw==================
      this._elementsToClear.push( this.renderAxisLine());

      tLabels.forEach( measureOneBin);
      while( tLabelSpecs.length > tNumBins) {
        var tSpec = tLabelSpecs.pop();
        tSpec.element.remove();
      }
      if( tCollision) // labels must be perpendicular to axis
        tRotation = tIsHorizontal ? -90 : 0;
      tLabelSpecs.forEach( drawOneCell);

      this.set('labelSpecs', tLabelSpecs);

      this.renderLabel();
      // By changing maxLabelExtent we can trigger notification that causes the graph to re-layout
      // axes and plot if needed.
      var tNewExtent;
      switch (tOrientation) {
        case DG.GraphTypes.EOrientation.kHorizontal:
          tNewExtent = (tRotation === 0) ? tMaxHeight : tMaxWidth;
          break;
        case DG.GraphTypes.EOrientation.kVertical:
          tNewExtent = (tRotation === 0) ? tMaxWidth : tMaxHeight;
          break;
      }
      this.setIfChanged('maxLabelExtent', tNewExtent);
    }

  };
}())
);

<commit_msg>[#171285373] Bug Fix: Binned plot axis doesn't update properly when new data comes in.<commit_after>// ==========================================================================
//                            DG.BinnedAxisView
//
//  Author:   William Finzer
//
//  Copyright (c) 2019 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

sc_require('components/graph/axes/axis_view');

/** @class  DG.BinnedAxisView - The view for a graph axis that displays numeric bins.

 @extends DG.AxisView
 */
DG.BinnedAxisView = DG.AxisView.extend( (function() {
  var kTickLength = 4,
      kAxisGap = 2;

  return {
    /** @scope DG.BinnedAxisView.prototype */

    /**
     Number of pixels required from the axis line to the edge of the graph view
     @property { Number }
     */
    desiredExtent: function() {
      var kWidthFudge = 5;
      return sc_super() + kTickLength + kAxisGap + kWidthFudge + this.get('maxLabelExtent');
    }.property('maxLabelExtent'),

    /**
     * When we are the "other" axis, our partner needs to know how much to offset pixelMin.
     * For me, it's the same as desiredExtent
     * @property {Number}
     */
    pixelMinOffset: function() {
      return this.get('desiredExtent');
    }.property('desiredExtent'),

    /**
     It's not clear whether this is a numeric axis or not
     @property { Boolean }
     */
    isNumeric: true,

    /**
     * @property {Boolean}
     */
    centering: true,

    /**
     @property {Number} Each time we draw the axis, we set this property to the maximum width
     of the label strings. Note that this will change depending not only on the length of the
     strings but on the rotation of the labels.
     */
    maxLabelExtent: 0,

    allowCellBoundaries: false,

    numberOfBins: function() {
      return this.getPath('model.binnedPlotModel.totalNumberOfBins');
    }.property(),
    numberOfBinsDidChange: function() {
      this.notifyPropertyChange( 'numberOfBins');
      this.displayDidChange();
    }.observes('model.binnedPlotModel.totalNumberOfBins'),

    /**
     * @return { Number} in pixels
     */
    binWidth: function() {
      var tNumBins = this.get('numberOfBins');

      return Math.abs(this.get('pixelMax') - this.get('pixelMin')) / tNumBins;
    }.property('numberOfBins'),

    labelSpecs: null,

    /**
     *
     * @param iBinNum {Number}
     * @return {Number} screen coordinate of center of bin
     */
    binToCoordinate: function( iBinNum) {
      var tOffset = (iBinNum + 0.5) * this.get('binWidth');
      if (this.get('orientation') === DG.GraphTypes.EOrientation.kVertical)
        tOffset = -tOffset;
      return this.get('pixelMin') + tOffset;
    },

    /**
     *
     * @param iWorldValue
     * @return {Number} in screen coordinates
     */
    dataToCoordinate: function( iWorldValue) {
      return this.binToCoordinate( Math.floor( (iWorldValue - this.getPath( 'model.binnedPlotModel.alignment')) /
        this.getPath('model.binnedPlotModel.width')));
    },

    binnedPlotModelWidthOrAlignmentDidChange: function() {
      this.displayDidChange();
    }.observes('model.binnedPlotModel.width', 'model.binnedPlotModel.alignment'),

    /**
     Since I'm a leaf class I implement doDraw.
     */
    doDraw: function doDraw() {

      // We can get stuck if we have height or width of zero
      var tFrame = this.get('frame');
      if( !tFrame || (tFrame.height === 0 || tFrame.width === 0))
        return;

      var this_ = this,
          kHorizontalOrientations = [DG.GraphTypes.EOrientation.kHorizontal, DG.GraphTypes.EOrientation.kTop],
          tModel = this.get('model'),
          tNumBins = tModel.get('numberOfBins'),
          tBaseline = this_.get('axisLineCoordinate'),
          tOrientation = this.get('orientation'),
          tIsHorizontal = kHorizontalOrientations.indexOf( tOrientation) >= 0,
          tRotation = tIsHorizontal ? 0 : -90, // default to parallel to axis
          tMaxHeight = DG.RenderingUtilities.kDefaultFontHeight,  // So there will be a default extent
          tCentering = this.get('centering'),
          tTickOffset = tCentering ? 0 : this.get('binWidth') / 2,
          tAnchor = tCentering ? 'middle' : 'start',
          tMaxWidth = tMaxHeight,
          tLabels = this.getPath('model.binLabels'),
          tLabelSpecs = this.get('labelSpecs') || [],
          tCollision = false,
          kCollisionPadding = 5,
          tPrevLabelEnd;

      function measureOneBin( iBinLabelAndTitle, iBinNum) {
        var tCoord = this_.binToCoordinate(iBinNum);
        if( !isFinite( tCoord)) {
          return;
        }
        var tTextElement;
        if( !tLabelSpecs[iBinNum]) {
          tTextElement = this_.get('paper').text(0, 0, iBinLabelAndTitle.label)
              .addClass('dg-axis-tick-label')
              .addClass('dg-binned-axis-label');
        }
        else {
          tTextElement = tLabelSpecs[ iBinNum].element;
          tTextElement.attr('text', iBinLabelAndTitle.label);
        }
        tTextElement.attr('title', iBinLabelAndTitle.title);
        var tTextExtent = DG.RenderingUtilities.getExtentForTextElement(
                          tTextElement, DG.RenderingUtilities.kDefaultFontHeight, true /* compute with no transform */);

        tTextElement.binNum = iBinNum;
        tLabelSpecs[iBinNum] = { element: tTextElement, coord: tCoord,
                      height: tTextExtent.height, width: tTextExtent.width };

        tMaxHeight = Math.max( tMaxHeight, tTextExtent.height);
        tMaxWidth = Math.max( tMaxWidth, tTextExtent.width);
        if(SC.none( tPrevLabelEnd)) {
          tCollision = tTextExtent.width > this_.get('binWidth');
          tPrevLabelEnd = tIsHorizontal ? tCoord + tTextExtent.width / 2 : tCoord - tTextExtent.width / 2;
        }
        else if( tIsHorizontal) {
          tCollision = tCollision || (tCoord - tTextExtent.width / 2 < tPrevLabelEnd + kCollisionPadding);
          tPrevLabelEnd = (tCoord + tTextExtent.width / 2);
        }
        else {  // vertical
          tCollision = tCollision || (tCoord + tTextExtent.width / 2 > tPrevLabelEnd - kCollisionPadding);
          tPrevLabelEnd = (tCoord - tTextExtent.width / 2);
        }
      } // measureOneBin

      // iLabelSpec has form { element: {Raphael element}, coord: {Number}, height: {Number}, width: {Number} }
      function drawOneCell( iLabelSpec, iIndex) {
        var tCoord = iLabelSpec.coord,
            tLabelX, tLabelY;
        switch( this_.get('orientation')) {
          case DG.GraphTypes.EOrientation.kVertical:
            this_._elementsToClear.push(
              this_.get('paper').line( tBaseline, tCoord + tTickOffset, tBaseline - kTickLength, tCoord + tTickOffset)
                .attr( { stroke: DG.PlotUtilities.kAxisColor }));
            tLabelX = tBaseline - kTickLength - kAxisGap - iLabelSpec.height / 3;
            tLabelY = tCoord + tTickOffset - ((iIndex === 0 && !tCentering) ? iLabelSpec.height / 2 : 0);
            if( tRotation === 0) {
              tAnchor = 'end';
              if( iLabelSpec.width > tLabelX && tLabelX > 10) {
                DG.RenderingUtilities.elideToFit( iLabelSpec.element, tLabelX);
              }
            }
            break;

          case DG.GraphTypes.EOrientation.kHorizontal:
            this_._elementsToClear.push(
              this_.get('paper').line( tCoord - tTickOffset, tBaseline, tCoord - tTickOffset, tBaseline + kTickLength)
                .attr( { stroke: DG.PlotUtilities.kAxisColor }));
            tLabelX = tCoord - tTickOffset + 1;
            tLabelY = tBaseline + kTickLength + kAxisGap + iLabelSpec.height / 3;
            if( tRotation === -90) {
              tAnchor = 'end';
              if( iIndex === 0 && !tCentering)
                tLabelX += iLabelSpec.height / 3;
              if( iLabelSpec.width > tFrame.height - tLabelY && tFrame.height - tLabelY > 10)
                DG.RenderingUtilities.elideToFit( iLabelSpec.element, tFrame.height - tLabelY);
            }
            break;
        }
        iLabelSpec.element.attr( { x: tLabelX, y: tLabelY, 'text-anchor': tAnchor });
        DG.RenderingUtilities.rotateText( iLabelSpec.element, tRotation, tLabelX, tLabelY);
      } // drawOneCell

      //==========Main body of doDraw==================
      this._elementsToClear.push( this.renderAxisLine());

      tLabels.forEach( measureOneBin);
      while( tLabelSpecs.length > tNumBins) {
        var tSpec = tLabelSpecs.pop();
        tSpec.element.remove();
      }
      if( tCollision) // labels must be perpendicular to axis
        tRotation = tIsHorizontal ? -90 : 0;
      tLabelSpecs.forEach( drawOneCell);

      this.set('labelSpecs', tLabelSpecs);

      this.renderLabel();
      // By changing maxLabelExtent we can trigger notification that causes the graph to re-layout
      // axes and plot if needed.
      var tNewExtent;
      switch (tOrientation) {
        case DG.GraphTypes.EOrientation.kHorizontal:
          tNewExtent = (tRotation === 0) ? tMaxHeight : tMaxWidth;
          break;
        case DG.GraphTypes.EOrientation.kVertical:
          tNewExtent = (tRotation === 0) ? tMaxWidth : tMaxHeight;
          break;
      }
      this.setIfChanged('maxLabelExtent', tNewExtent);
    }

  };
}())
);

<|endoftext|>


<commit_before>(function() {
  'use strict';

angular.module('web')
    .service('api', RestApiService);

function RestApiService($http, $q, $auth, $log, $mdToast) {

    var self = this;
    // Api URI
    self.API_URL = apiUrl + '/';
    self.AUTH_URL = authApiUrl + '/';
    self.FRONTEND_URL = serverUrl + '/';

    self.endpoints = {
        check: 'status',
        logged: 'profile',
        login: 'login',
        // logout: 'logout',
        logout: 'loggedout',
        admin: 'verifyadmin',
        register: 'doregistration',
    };

    self.getOrDefault = function (value, mydefault) {
        return typeof value !== 'undefined' ? value : mydefault;
    };
    self.checkToken = function () {
        return $auth.getToken();
    };

    self.apiCall = function (endpoint, method, data, id, returnRawResponse, skipPromiseResolve)
    {

      ////////////////////////
        //DEFAULTS
        returnRawResponse = self.getOrDefault(returnRawResponse, false);
        endpoint = self.getOrDefault(endpoint, self.endpoints.check);
        if (typeof id !== 'undefined' && method != 'POST') {
            endpoint += '/' + id;
        }
        method = self.getOrDefault(method, 'GET');
        skipPromiseResolve = self.getOrDefault(skipPromiseResolve, false);

        var params = {};
        if (method == 'GET') {
            params = self.getOrDefault(data, {});
            data = {};
        } else if (method == 'POST') {
            data = self.getOrDefault(data, {});
        }

        var currentUrl = self.API_URL + endpoint;
//////////////////////////////
// WARNING PORCATA
        if (endpoint == 'login'
            // || endpoint == 'logout'
            || endpoint == self.endpoints.logged)
        {
            currentUrl = self.AUTH_URL + endpoint;
        }
        if (endpoint == self.endpoints.register
            || endpoint == self.endpoints.logout)
        {
            currentUrl = self.FRONTEND_URL + endpoint;
        }
//////////////////////////////

        var token = self.checkToken(),
            timeout = 5500,
            req = {
                method: method,
                url: currentUrl,
                headers: {
                    'Content-Type': 'application/json',
                    // 'Authentication-Token': token,
                    'Authorization': 'Bearer ' + token,
                },
                data: data,
                params: params,
                timeout: timeout,
            }

        if (skipPromiseResolve) return $http(req);

        return $http(req).then(
            function successCallback(response) {
                //$log.debug("API call successful");

                if (returnRawResponse) return response;

                return response.data.Response;
          }, function errorCallback(response) {
                $log.warn("API failed to call")

                if (returnRawResponse) return $q.reject(response);

                if (!response.data || !response.data.hasOwnProperty('Response')) {
                    return null;
                } else if (typeof response.data.Response === 'undefined') {
                    return null;
                }

                return $q.reject(response.data.Response);
        });
    }

    self.verify = function(logged)
    {
        var endpoint = self.endpoints.check;
        if (logged) {
            endpoint = self.endpoints.logged;
        }
        return self.apiCall(endpoint, 'GET', undefined, undefined, true)
            .then(function (response) {
                $log.debug("API verify:", response);
                if (response.status > 250) {
                    // API available
                    return false;
                } else if (response.status < 0) {
                    // API offline
                    return null;
                }
                return true;
            });
    }
}

})();
<commit_msg>Fix user disconnection when token become invalid [before the fix angularj entered an infinte loop]<commit_after>(function() {
  'use strict';

angular.module('web')
    .service('api', RestApiService);

function RestApiService($http, $q, $auth, $log, $mdToast) {

    var self = this;
    // Api URI
    self.API_URL = apiUrl + '/';
    self.AUTH_URL = authApiUrl + '/';
    self.FRONTEND_URL = serverUrl + '/';

    self.endpoints = {
        check: 'status',
        logged: 'profile',
        login: 'login',
        // logout: 'logout',
        logout: 'loggedout',
        admin: 'verifyadmin',
        register: 'doregistration',
    };

    self.getOrDefault = function (value, mydefault) {
        return typeof value !== 'undefined' ? value : mydefault;
    };
    self.checkToken = function () {
        return $auth.getToken();
    };

    self.apiCall = function (endpoint, method, data, id, returnRawResponse, skipPromiseResolve)
    {

      ////////////////////////
        //DEFAULTS
        returnRawResponse = self.getOrDefault(returnRawResponse, false);
        endpoint = self.getOrDefault(endpoint, self.endpoints.check);
        if (typeof id !== 'undefined' && method != 'POST') {
            endpoint += '/' + id;
        }
        method = self.getOrDefault(method, 'GET');
        skipPromiseResolve = self.getOrDefault(skipPromiseResolve, false);

        var params = {};
        if (method == 'GET') {
            params = self.getOrDefault(data, {});
            data = {};
        } else if (method == 'POST') {
            data = self.getOrDefault(data, {});
        }

        var currentUrl = self.API_URL + endpoint;
//////////////////////////////
// WARNING PORCATA
        if (endpoint == 'login'
            // || endpoint == 'logout'
            || endpoint == self.endpoints.logged)
        {
            currentUrl = self.AUTH_URL + endpoint;
        }
        if (endpoint == self.endpoints.register
            || endpoint == self.endpoints.logout)
        {
            currentUrl = self.FRONTEND_URL + endpoint;
        }
//////////////////////////////

        var token = self.checkToken(),
            timeout = 5500,
            req = {
                method: method,
                url: currentUrl,
                headers: {
                    'Content-Type': 'application/json',
                    // 'Authentication-Token': token,
                    'Authorization': 'Bearer ' + token,
                },
                data: data,
                params: params,
                timeout: timeout,
            }

        if (skipPromiseResolve) return $http(req);

        return $http(req).then(
            function successCallback(response) {
                //$log.debug("API call successful");

                if (returnRawResponse) return response;

                return response.data.Response;
          }, function errorCallback(response) {
                $log.warn("API failed to call")

                if (returnRawResponse) return $q.reject(response);

                if (!response.data || !response.data.hasOwnProperty('Response')) {
                    return null;
                } else if (typeof response.data.Response === 'undefined') {
                    return null;
                }

                return $q.reject(response.data.Response);
        });
    }

    self.verify = function(logged)
    {
        var endpoint = self.endpoints.check;
        if (logged) {
            endpoint = self.endpoints.logged;
        }
        return self.apiCall(endpoint, 'GET', undefined, undefined, true)
            .then(function successCallback(response) {
                $log.debug("API verify:", response);
                if (response.status < 0) {
                    // API offline
                    return null;
                }
                return true;
            }, function errorCallback(response) {
                return false
            });
    }
}

})();
<|endoftext|>


<commit_before>// This library scans for Eddystone beacons and translates their
// advertisements into user-friendly variables.
// The protocol specification is available at:
// https://github.com/google/eddystone

// prerequisites
evothings.loadScripts([
	'libs/evothings/easyble/easyble.js',
])

evothings.eddystone = {};

(function() {
// constants
var BLUETOOTH_BASE_UUID = '-0000-1000-8000-00805f9b34fb';

// false when scanning is off. true when on.
var isScanning = false;

/** Starts scanning for Eddystone devices.
*
Found devices and errors will be reported to the supplied callbacks.

*
Will keep scanning indefinitely until you call stopScan().

* To conserve energy, call stopScan() as soon as you've found the device you're looking for.
*
Calling this function while scanning is in progress will fail.

*
* @param {scanCallback} win
* @param {failCallback} fail
*/
evothings.eddystone.startScan = function(win, fail) {
	// If scanning is already in progress, fail.
	if(isScanning) {
		fail("Scanning already in progress!");
		return;
	}

	isScanning = true;

	// The device object given in this callback is reused by easyble.
	// Therefore we can store data in it and expect to have the data still be there
	// on the next callback with the same device.
	evothings.easyble.startScan(function(device) {
		// A device might be an Eddystone if it has advertisementData...
		var ad = device.advertisementData;
		if(!ad) return;
		// With serviceData...
		var sd = ad.kCBAdvDataServiceData;
		if(!sd) return;
		// And the 0xFEAA service.
		var base64data = sd['0000feaa'+BLUETOOTH_BASE_UUID];
		if(!base64data) return;
		var byteArray = evothings.util.base64DecToArr(base64data);

		// If the data matches one of the Eddystone frame formats,
		// we can forward it to the user.
		if(parseFrameUID(device, byteArray, win, fail)) return;
		if(parseFrameURL(device, byteArray, win, fail)) return;
		if(parseFrameTLM(device, byteArray, win, fail)) return;

	}, function(error) {
		fail(error);
	});
}

/** This function is a parameter to startScan() and is called when a new device is discovered.
* @callback scanCallback
* @param {EddystoneDevice} device
*/

/** Object representing a BLE device. Inherits from evothings.easyble.EasyBLEDevice.
* All uninherited properties are optional; they may be missing.
* @typedef {Object} EddystoneDevice
* @property {string} url - An Internet URL.
* @property {number} txPower - A signed integer, the signal strength in decibels, factory-measured at a range of 0 meters.
* @property {Uint8Array} nid - 10-byte namespace ID.
* @property {Uint8Array} bid - 6-byte beacon ID.
* @property {number} voltage - Device's battery voltage, in millivolts, or 0 (zero) if device is not battery-powered.
* @property {number} temperature - Device's ambient temperature in 256:ths of degrees Celcius, or 0x8000 if device has no thermometer.
* @property {number} adv_cnt - Count of advertisement frames sent since device's startup.
* @property {number} dsec_cnt - Time since device's startup, in deci-seconds (10 units equals 1 second).
*/

/** Stop scanning for Eddystone devices.
*/
evothings.eddystone.stopScan = function() {
	evothings.easyble.stopScan();
	isScanning = false;
}

// Return true on frame type recognition, false otherwise.
function parseFrameUID(device, data, win, fail) {
	if(data[0] != 0x00) return false;
	// The UID frame has 18 bytes + 2 bytes reserved for future use
	// https://github.com/google/eddystone/tree/master/eddystone-uid
	// Check that we got at least 18 bytes.
	if(data.byteLength < 18) {
		fail("UID frame: invalid byteLength: "+data.byteLength);
		return true;
	}
	device.txPower = evothings.util.littleEndianToInt8(data, 1);
	device.nid = data.subarray(2, 12);  // Namespace ID.
	device.bid = data.subarray(12, 18); // Beacon ID.
	win(device);
	return true;
}

function parseFrameURL(device, data, win, fail) {
	if(data[0] != 0x10) return false;
	if(data.byteLength < 4) {
		fail("URL frame: invalid byteLength: "+data.byteLength);
		return true;
	}
	device.txPower = evothings.util.littleEndianToInt8(data, 1);
	var url;
	// URL scheme prefix
	switch(data[2]) {
		case 0: url = 'http://www.'; break;
		case 1: url = 'https://www.'; break;
		case 2: url = 'http://'; break;
		case 3: url = 'https://'; break;
		default: fail("URL frame: invalid prefix: "+data[2]); return true;
	}
	// Process each byte in sequence.
	var i = 3;
	while(i < data.byteLength) {
		var c = data[i];
		// A byte is either a top-domain shortcut, or a printable ascii character.
		if(c < 14) {
			switch(c) {
				case 0: url += '.com/'; break;
				case 1: url += '.org/'; break;
				case 2: url += '.edu/'; break;
				case 3: url += '.net/'; break;
				case 4: url += '.info/'; break;
				case 5: url += '.biz/'; break;
				case 6: url += '.gov/'; break;
				case 7: url += '.com'; break;
				case 8: url += '.org'; break;
				case 9: url += '.edu'; break;
				case 10: url += '.net'; break;
				case 11: url += '.info'; break;
				case 12: url += '.biz'; break;
				case 13: url += '.gov'; break;
			}
		} else if(c < 32 || c >= 127) {
			// Unprintables are not allowed.
			fail("URL frame: invalid character: "+data[2]);
			return true;
		} else {
			url += String.fromCharCode(c);
		}

		i += 1;
	}
	device.url = url;
	win(device);
	return true;
}

function parseFrameTLM(device, data, win, fail) {
	if(data[0] != 0x20) return false;
	if(data[1] != 0x00) {
		fail("TLM frame: unknown version: "+data[1]);
		return true;
	}
	if(data.byteLength != 14) {
		fail("TLM frame: invalid byteLength: "+data.byteLength);
		return true;
	}

	device.voltage = evothings.util.bigEndianToUint16(data, 2);

	var temp = evothings.util.bigEndianToUint16(data, 4);
	if(temp == 0x8000)
		device.temperature = 0x8000;
	else
		device.temperature = evothings.util.bigEndianToInt16(data, 4) / 256.0;

	device.adv_cnt = evothings.util.bigEndianToUint32(data, 6);
	device.dsec_cnt = evothings.util.bigEndianToUint32(data, 10);

	win(device);
	return true;
}

})();
<commit_msg>Added file name and inserted semicolon before opening left paren.<commit_after>// File: eddystone.js

// This library scans for Eddystone beacons and translates their
// advertisements into user-friendly variables.
// The protocol specification is available at:
// https://github.com/google/eddystone

// prerequisites
evothings.loadScripts([
	'libs/evothings/easyble/easyble.js',
])

evothings.eddystone = {};

;(function() {
// constants
var BLUETOOTH_BASE_UUID = '-0000-1000-8000-00805f9b34fb';

// false when scanning is off. true when on.
var isScanning = false;

/** Starts scanning for Eddystone devices.
*
Found devices and errors will be reported to the supplied callbacks.

*
Will keep scanning indefinitely until you call stopScan().

* To conserve energy, call stopScan() as soon as you've found the device you're looking for.
*
Calling this function while scanning is in progress will fail.

*
* @param {scanCallback} win
* @param {failCallback} fail
*/
evothings.eddystone.startScan = function(win, fail) {
	// If scanning is already in progress, fail.
	if(isScanning) {
		fail("Scanning already in progress!");
		return;
	}

	isScanning = true;

	// The device object given in this callback is reused by easyble.
	// Therefore we can store data in it and expect to have the data still be there
	// on the next callback with the same device.
	evothings.easyble.startScan(function(device) {
		// A device might be an Eddystone if it has advertisementData...
		var ad = device.advertisementData;
		if(!ad) return;
		// With serviceData...
		var sd = ad.kCBAdvDataServiceData;
		if(!sd) return;
		// And the 0xFEAA service.
		var base64data = sd['0000feaa'+BLUETOOTH_BASE_UUID];
		if(!base64data) return;
		var byteArray = evothings.util.base64DecToArr(base64data);

		// If the data matches one of the Eddystone frame formats,
		// we can forward it to the user.
		if(parseFrameUID(device, byteArray, win, fail)) return;
		if(parseFrameURL(device, byteArray, win, fail)) return;
		if(parseFrameTLM(device, byteArray, win, fail)) return;

	}, function(error) {
		fail(error);
	});
}

/** This function is a parameter to startScan() and is called when a new device is discovered.
* @callback scanCallback
* @param {EddystoneDevice} device
*/

/** Object representing a BLE device. Inherits from evothings.easyble.EasyBLEDevice.
* All uninherited properties are optional; they may be missing.
* @typedef {Object} EddystoneDevice
* @property {string} url - An Internet URL.
* @property {number} txPower - A signed integer, the signal strength in decibels, factory-measured at a range of 0 meters.
* @property {Uint8Array} nid - 10-byte namespace ID.
* @property {Uint8Array} bid - 6-byte beacon ID.
* @property {number} voltage - Device's battery voltage, in millivolts, or 0 (zero) if device is not battery-powered.
* @property {number} temperature - Device's ambient temperature in 256:ths of degrees Celcius, or 0x8000 if device has no thermometer.
* @property {number} adv_cnt - Count of advertisement frames sent since device's startup.
* @property {number} dsec_cnt - Time since device's startup, in deci-seconds (10 units equals 1 second).
*/

/** Stop scanning for Eddystone devices.
*/
evothings.eddystone.stopScan = function() {
	evothings.easyble.stopScan();
	isScanning = false;
}

// Return true on frame type recognition, false otherwise.
function parseFrameUID(device, data, win, fail) {
	if(data[0] != 0x00) return false;
	// The UID frame has 18 bytes + 2 bytes reserved for future use
	// https://github.com/google/eddystone/tree/master/eddystone-uid
	// Check that we got at least 18 bytes.
	if(data.byteLength < 18) {
		fail("UID frame: invalid byteLength: "+data.byteLength);
		return true;
	}
	device.txPower = evothings.util.littleEndianToInt8(data, 1);
	device.nid = data.subarray(2, 12);  // Namespace ID.
	device.bid = data.subarray(12, 18); // Beacon ID.
	win(device);
	return true;
}

function parseFrameURL(device, data, win, fail) {
	if(data[0] != 0x10) return false;
	if(data.byteLength < 4) {
		fail("URL frame: invalid byteLength: "+data.byteLength);
		return true;
	}
	device.txPower = evothings.util.littleEndianToInt8(data, 1);
	var url;
	// URL scheme prefix
	switch(data[2]) {
		case 0: url = 'http://www.'; break;
		case 1: url = 'https://www.'; break;
		case 2: url = 'http://'; break;
		case 3: url = 'https://'; break;
		default: fail("URL frame: invalid prefix: "+data[2]); return true;
	}
	// Process each byte in sequence.
	var i = 3;
	while(i < data.byteLength) {
		var c = data[i];
		// A byte is either a top-domain shortcut, or a printable ascii character.
		if(c < 14) {
			switch(c) {
				case 0: url += '.com/'; break;
				case 1: url += '.org/'; break;
				case 2: url += '.edu/'; break;
				case 3: url += '.net/'; break;
				case 4: url += '.info/'; break;
				case 5: url += '.biz/'; break;
				case 6: url += '.gov/'; break;
				case 7: url += '.com'; break;
				case 8: url += '.org'; break;
				case 9: url += '.edu'; break;
				case 10: url += '.net'; break;
				case 11: url += '.info'; break;
				case 12: url += '.biz'; break;
				case 13: url += '.gov'; break;
			}
		} else if(c < 32 || c >= 127) {
			// Unprintables are not allowed.
			fail("URL frame: invalid character: "+data[2]);
			return true;
		} else {
			url += String.fromCharCode(c);
		}

		i += 1;
	}
	device.url = url;
	win(device);
	return true;
}

function parseFrameTLM(device, data, win, fail) {
	if(data[0] != 0x20) return false;
	if(data[1] != 0x00) {
		fail("TLM frame: unknown version: "+data[1]);
		return true;
	}
	if(data.byteLength != 14) {
		fail("TLM frame: invalid byteLength: "+data.byteLength);
		return true;
	}

	device.voltage = evothings.util.bigEndianToUint16(data, 2);

	var temp = evothings.util.bigEndianToUint16(data, 4);
	if(temp == 0x8000)
		device.temperature = 0x8000;
	else
		device.temperature = evothings.util.bigEndianToInt16(data, 4) / 256.0;

	device.adv_cnt = evothings.util.bigEndianToUint32(data, 6);
	device.dsec_cnt = evothings.util.bigEndianToUint32(data, 10);

	win(device);
	return true;
}

})();
<|endoftext|>


<commit_before>"use strict";
var PORT = 4200;
var path = require('path');

//to control iRobot create2
var fs = require("fs");
var Repl = require("repl");
var Devices = require("../src/detect");

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);

/*Devices.getArduinoComName().then(function (port) {
  board = new five.Board({
    "repl": false,
    port: port
  });
  board.on("ready", boardHandler);
  board.on("fail", function (event) {
    console.error(event);
  });
});*/

Devices.getArduinoComName().then(function (port) {
  console.log("hello arduino board");
  const five = require('johnny-five');
  board = new five.Board({
    "repl": false,
    port: port
  });
  board.on("ready", boardHandler());
  board.on("fail", function (event) {
    console.error(event);
  });
});

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, '../client/index.html'));
});

app.use("/", express.static(path.join(__dirname, '../client')));
app.use("/assets", express.static(path.join(__dirname, '../client/assets')));
http.listen(PORT, function () {
  console.log('Listen on ', PORT);
});

let led = null;

function boardHandler() {
  console.log("Board ready, lets add light");
  led = new five.Led(11);
  led.on();
};

io.sockets.on('connection', function(socket) {
  console.log("hello socket");
  socket.on('ledStatus', function(status) {
    if (status) {
      console.log("Led on!!!");
      led.on();
    } else {
      console.log("Led off...");
      led.stop().off();
    }
  });
});
<commit_msg>edit debug-led-blink<commit_after>"use strict";
var PORT = 4200;
var path = require('path');

//to control iRobot create2
var fs = require("fs");
var Repl = require("repl");
var Devices = require("../src/detect");

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);

/*Devices.getArduinoComName().then(function (port) {
  board = new five.Board({
    "repl": false,
    port: port
  });
  board.on("ready", boardHandler);
  board.on("fail", function (event) {
    console.error(event);
  });
});*/
const five = require('johnny-five');

Devices.getArduinoComName().then(function (port) {
  console.log("hello arduino board");
  board = new five.Board({
    "repl": false,
    port: port
  });
  board.on("ready", function(){
    console.log("hello ready");
  });
  board.on("fail", function (event) {
    console.error(event);
  });
});

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, '../client/index.html'));
});

app.use("/", express.static(path.join(__dirname, '../client')));
app.use("/assets", express.static(path.join(__dirname, '../client/assets')));
http.listen(PORT, function () {
  console.log('Listen on ', PORT);
});

let led = null;

function boardHandler() {
  console.log("Board ready, lets add light");
  led = new five.Led(11);
  led.on();
};

io.sockets.on('connection', function(socket) {
  console.log("hello socket");
  socket.on('ledStatus', function(status) {
    if (status) {
      console.log("Led on!!!");
      led.on();
    } else {
      console.log("Led off...");
      led.stop().off();
    }
  });
});
<|endoftext|>


<commit_before>describe("authorization", function() {

  beforeEach(function() {
    Prompts.find().forEach(function (p) {
      Prompts.remove({_id: p._id});
    });
  });

  it("should not let a non-owner add Prompts", function(done) {
    withNonOwner(function() {
      Prompts.insert("Should anyone be able to add prompts?", function(error, result) {

        // TODO: not checking for undefined error first passes? what?
        expect(error).not.toBeUndefined();
        expect(error.error).toBe(403);

        done();
      });
    });
  });

  it("should let an owner add Prompts", function (done) {
    // Given
     withOwner(function() {
      // When
      Prompts.insert("Should owners be able to add prompts?", function(error, result) {

        // Then
        expect(error).toBeUndefined();

        done();
      });
    });
  });

});
<commit_msg>don't check for undefined any more<commit_after>describe("authorization", function() {

  beforeEach(function() {
    Prompts.find().forEach(function (p) {
      Prompts.remove({_id: p._id});
    });
  });

  it("should not let a non-owner add Prompts", function(done) {
    // Given
    withNonOwner(function() {
      // When
      Prompts.insert("Should anyone be able to add prompts?", function(error, result) {

        // Then
        expect(error.error).toBe(403);

        done();
      });
    });
  });

  it("should let an owner add Prompts", function (done) {
    // Given
     withOwner(function() {
      // When
      Prompts.insert("Should owners be able to add prompts?", function(error, result) {

        // Then
        expect(error).toBeUndefined();

        done();
      });
    });
  });

});
<|endoftext|>


<commit_before>
var str1 = `abcde`;

var str2 = `abcde${str1}abcde`;

var str3 = `abcde${(function () { return 'abc'; }())}abcde`;

var str4 = `abcde${({prop1: 1, prop2: 'p'})['prop1']}abcde`;

var str5 = `abcde${({prop1: 1, prop2: `edcba${1}ebcda`})['prop1']}abcde`;

var str6 = `abcde${({
  prop1: 1,
  prop2: `edcba${1}ebcda`
})['prop1']}abcde`;

var str7 = `abcde${(function () {
  return `edcba${str1 + `zz${1}zz`}edcba`;
}())}abcde`;

var str8 = tag1`abcd ${a}`

var str9 = `s${`<tag attr=${exp}>${exp}</tag>`}`
<commit_msg>Add more complex template string<commit_after>
var str1 = `abcde`;

var str2 = `abcde${str1}abcde`;

var str3 = `abcde${(function () { return 'abc'; }())}abcde`;

var str4 = `abcde${({prop1: 1, prop2: 'p'})['prop1']}abcde`;

var str5 = `abcde${({prop1: 1, prop2: `edcba${1}ebcda`})['prop1']}abcde`;

var str6 = `abcde${({
  prop1: 1,
  prop2: `edcba${1}ebcda`
})['prop1']}abcde`;

var str7 = `abcde${(function () {
  return `edcba${str1 + `zz${1}zz`}edcba`;
}())}abcde`;

var str8 = tag1`abcd ${a}`

var str9 = `s${`<tag attr=${exp}>${exp}</tag>`}`

var str10 = `<tag attr=${exp}>${exp}</tag>`
`${`<tag attr=${exp}>${exp}</tag>`}`
<|endoftext|>