<commit_before>//----------------------------------------------------------------------------
//  Copyright (C) 2013 The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// ContainerWidget
//============================================================================

/**
 * @module IPython
 * @namespace IPython
 **/

define(["notebook/js/widget"], function(widget_manager) {
    var ContainerModel = IPython.WidgetModel.extend({});
    widget_manager.register_widget_model('ContainerWidgetModel', ContainerModel);

    var ContainerView = IPython.WidgetView.extend({

        render: function(){
            this.$el
                .addClass('widget-container');
        },

        update: function(){

            // Apply flexible box model properties by adding and removing
            // corrosponding CSS classes.
            // Defined in IPython/html/static/base/less/flexbox.less
            this.set_flex_property('vbox', this.model.get('_vbox'));
            this.set_flex_property('hbox', this.model.get('_hbox'));
            this.set_flex_property('start', this.model.get('_pack_start'));
            this.set_flex_property('center', this.model.get('_pack_center'));
            this.set_flex_property('end', this.model.get('_pack_end'));
            this.set_flex_property('align-start', this.model.get('_align_start'));
            this.set_flex_property('align-center', this.model.get('_align_center'));
            this.set_flex_property('align-end', this.model.get('_align_end'));
            this.set_flex_property('box-flex0', this.model.get('_flex0'));
            this.set_flex_property('box-flex1', this.model.get('_flex1'));
            this.set_flex_property('box-flex2', this.model.get('_flex2'));

            return IPython.WidgetView.prototype.update.call(this);
        },

        set_flex_property: function(property_name, enabled) {
            if (enabled) {
                this.$el.addClass(property_name);
            } else {
                this.$el.removeClass(property_name);
            }
        },

        display_child: function(view) {
            this.$el.append(view.$el);
        },
    });

    widget_manager.register_widget_view('ContainerView', ContainerView);

    var ModalView = IPython.WidgetView.extend({

        render: function(){
            var that = this;
            this.$el
                .html('')
                .on("remove", function(){
                    that.$window.remove();
                });
            this.$window = $('
')
                .addClass('modal widget-modal')
                .appendTo($('#notebook-container'));
            var title_bar = $('
')
                .addClass('popover-title')
                .appendTo(this.$window);
            var that = this;
            $('<button />')
                .addClass('close')
                .html('×')
                .appendTo(title_bar)
                .click(function(){
                    that.hide();
                    event.stopPropagation();
                });
            this.$title = $('
')
                .addClass('widget-modal-title')
                .html(' ')
                .appendTo(title_bar);
            this.$body = $('
')
                .addClass('modal-body')
                .addClass('widget-container')
                .appendTo(this.$window);

            this.$show_button = $('<button />')
                .html(' ')
                .addClass('btn btn-info widget-modal-show')
                .appendTo(this.$el)
                .click(function(){
                    that.show();
                });

            this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
            this.$window.resizable();
            this._shown_once = false;
        },

        hide: function() {
            this.$window.hide();
            this.$show_button.removeClass('btn-info');
        },

        show: function() {
            this.$window.show();
            this.$show_button.addClass('btn-info');
            var position = this.$show_button.offset();
            this.$window.css('left', position.left + this.$show_button.outerWidth());
            this.$window.css('top', position.top);
        },

        update: function(){

            // Apply flexible box model properties by adding and removing
            // corrosponding CSS classes.
            // Defined in IPython/html/static/base/less/flexbox.less
            this.set_flex_property('vbox', this.model.get('_vbox'));
            this.set_flex_property('hbox', this.model.get('_hbox'));
            this.set_flex_property('start', this.model.get('_pack_start'));
            this.set_flex_property('center', this.model.get('_pack_center'));
            this.set_flex_property('end', this.model.get('_pack_end'));
            this.set_flex_property('align-start', this.model.get('_align_start'));
            this.set_flex_property('align-center', this.model.get('_align_center'));
            this.set_flex_property('align-end', this.model.get('_align_end'));
            this.set_flex_property('box-flex0', this.model.get('_flex0'));
            this.set_flex_property('box-flex1', this.model.get('_flex1'));
            this.set_flex_property('box-flex2', this.model.get('_flex2'));

            var description = this.model.get('description');
            description = description.replace(/ /g, ' ', 'm');
            description = description.replace(/\n/g, '
\n', 'm');
            if (description.length == 0) {
                this.$title.html(' '); // Preserve title height
            } else {
                this.$title.html(description);
            }

            var button_text = this.model.get('button_text');
            button_text = button_text.replace(/ /g, ' ', 'm');
            button_text = button_text.replace(/\n/g, '
\n', 'm');
            if (button_text.length == 0) {
                this.$show_button.html(' '); // Preserve button height
            } else {
                this.$show_button.html(button_text);
            }

            if (!this._shown_once) {
                this._shown_once = true;
                this.show();
            }

            return IPython.WidgetView.prototype.update.call(this);
        },

        set_flex_property: function(property_name, enabled) {
            if (enabled) {
                this.$body.addClass(property_name);
            } else {
                this.$body.removeClass(property_name);
            }
        },

        display_child: function(view) {
            this.$body.append(view.$el);
        },

    });

    widget_manager.register_widget_view('ModalView', ModalView);
});
<commit_msg>Fixed body container height not stretching to fill remainer of height<commit_after>//----------------------------------------------------------------------------
//  Copyright (C) 2013 The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// ContainerWidget
//============================================================================

/**
 * @module IPython
 * @namespace IPython
 **/

define(["notebook/js/widget"], function(widget_manager) {
    var ContainerModel = IPython.WidgetModel.extend({});
    widget_manager.register_widget_model('ContainerWidgetModel', ContainerModel);

    var ContainerView = IPython.WidgetView.extend({

        render: function(){
            this.$el
                .addClass('widget-container');
        },

        update: function(){

            // Apply flexible box model properties by adding and removing
            // corrosponding CSS classes.
            // Defined in IPython/html/static/base/less/flexbox.less
            this.set_flex_property('vbox', this.model.get('_vbox'));
            this.set_flex_property('hbox', this.model.get('_hbox'));
            this.set_flex_property('start', this.model.get('_pack_start'));
            this.set_flex_property('center', this.model.get('_pack_center'));
            this.set_flex_property('end', this.model.get('_pack_end'));
            this.set_flex_property('align-start', this.model.get('_align_start'));
            this.set_flex_property('align-center', this.model.get('_align_center'));
            this.set_flex_property('align-end', this.model.get('_align_end'));
            this.set_flex_property('box-flex0', this.model.get('_flex0'));
            this.set_flex_property('box-flex1', this.model.get('_flex1'));
            this.set_flex_property('box-flex2', this.model.get('_flex2'));

            return IPython.WidgetView.prototype.update.call(this);
        },

        set_flex_property: function(property_name, enabled) {
            if (enabled) {
                this.$el.addClass(property_name);
            } else {
                this.$el.removeClass(property_name);
            }
        },

        display_child: function(view) {
            this.$el.append(view.$el);
        },
    });

    widget_manager.register_widget_view('ContainerView', ContainerView);

    var ModalView = IPython.WidgetView.extend({

        render: function(){
            var that = this;
            this.$el
                .html('')
                .on("remove", function(){
                    that.$window.remove();
                });
            this.$window = $('
')
                .addClass('modal widget-modal')
                .appendTo($('#notebook-container'));
            this.$title_bar = $('
')
                .addClass('popover-title')
                .appendTo(this.$window);
            var that = this;
            $('<button />')
                .addClass('close')
                .html('×')
                .appendTo(this.$title_bar)
                .click(function(){
                    that.hide();
                    event.stopPropagation();
                });
            this.$title = $('
')
                .addClass('widget-modal-title')
                .html(' ')
                .appendTo(this.$title_bar);
            this.$body = $('
')
                .addClass('modal-body')
                .addClass('widget-container')
                .appendTo(this.$window);

            this.$show_button = $('<button />')
                .html(' ')
                .addClass('btn btn-info widget-modal-show')
                .appendTo(this.$el)
                .click(function(){
                    that.show();
                });

            this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
            this.$window.resizable();
            this.$window.on('resize', function(){
                that.$body.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
            })

            this._shown_once = false;
        },

        hide: function() {
            this.$window.hide();
            this.$show_button.removeClass('btn-info');
        },

        show: function() {
            this.$window.show();
            this.$show_button.addClass('btn-info');
            var position = this.$show_button.offset();
            this.$window.css('left', position.left + this.$show_button.outerWidth());
            this.$window.css('top', position.top);
        },

        update: function(){

            // Apply flexible box model properties by adding and removing
            // corrosponding CSS classes.
            // Defined in IPython/html/static/base/less/flexbox.less
            this.set_flex_property('vbox', this.model.get('_vbox'));
            this.set_flex_property('hbox', this.model.get('_hbox'));
            this.set_flex_property('start', this.model.get('_pack_start'));
            this.set_flex_property('center', this.model.get('_pack_center'));
            this.set_flex_property('end', this.model.get('_pack_end'));
            this.set_flex_property('align-start', this.model.get('_align_start'));
            this.set_flex_property('align-center', this.model.get('_align_center'));
            this.set_flex_property('align-end', this.model.get('_align_end'));
            this.set_flex_property('box-flex0', this.model.get('_flex0'));
            this.set_flex_property('box-flex1', this.model.get('_flex1'));
            this.set_flex_property('box-flex2', this.model.get('_flex2'));

            var description = this.model.get('description');
            description = description.replace(/ /g, ' ', 'm');
            description = description.replace(/\n/g, '
\n', 'm');
            if (description.length == 0) {
                this.$title.html(' '); // Preserve title height
            } else {
                this.$title.html(description);
            }

            var button_text = this.model.get('button_text');
            button_text = button_text.replace(/ /g, ' ', 'm');
            button_text = button_text.replace(/\n/g, '
\n', 'm');
            if (button_text.length == 0) {
                this.$show_button.html(' '); // Preserve button height
            } else {
                this.$show_button.html(button_text);
            }

            if (!this._shown_once) {
                this._shown_once = true;
                this.show();
            }

            return IPython.WidgetView.prototype.update.call(this);
        },

        set_flex_property: function(property_name, enabled) {
            if (enabled) {
                this.$body.addClass(property_name);
            } else {
                this.$body.removeClass(property_name);
            }
        },

        display_child: function(view) {
            this.$body.append(view.$el);
        },

    });

    widget_manager.register_widget_view('ModalView', ModalView);
});
<|endoftext|>


<commit_before>function ChapterStatsController(chapterJSON) {
  var ChapterStatsCtrl = this;
  ChapterStatsCtrl.chapter = chapterJSON.data;

  // entries

  function filterWeeklyEntries(startOfWeek, entries) {
    var endOfWeek = new Date();
    endOfWeek.setDate(startOfWeek.getDate() + 7);
    var weeksEntries = []
    for (i = 0; i < entries.length; i++) {
      var entryDay = new Date(entries[i].day);
      if (entryDay > startOfWeek && entryDay <= endOfWeek) {
        weeksEntries.push(entries[i]);
      }
    }
    return weeksEntries;
  }

  if (ChapterStatsCtrl.chapter.completed_at !== null) {
    var startOfThisWeek = new Date(ChapterStatsCtrl.chapter.completed_at);
    var startOfLastWeek = new Date(ChapterStatsCtrl.chapter.completed_at);
  } else {
    var startOfThisWeek = new Date();
    var startOfLastWeek = new Date();
  }

  startOfThisWeek.setDate(startOfThisWeek.getDate() - 7)
  startOfLastWeek.setDate(startOfLastWeek.getDate() - 14)

  var thisWeeksEntries = filterWeeklyEntries(startOfThisWeek, ChapterStatsCtrl.chapter.entries.slice(0, 7));
  var lastWeeksEntries = filterWeeklyEntries(startOfLastWeek, ChapterStatsCtrl.chapter.entries.slice(0, 14));

  console.log(ChapterStatsCtrl.chapter.this_weeks_measurements);
  console.log(thisWeeksEntries);
  console.log(ChapterStatsCtrl.chapter.last_weeks_measurements)
  console.log(lastWeeksEntries);

  // measurements

  function calculateWeeklyMeasurementAverages(measurements) {
    var weightVals = measurements.map(function(measurement) { return measurement.weight});
    var bodyfatVals = measurements.map(function(measurement) { return measurement.bodyfat; });
    var heightVals = measurements.map(function(measurement) { return measurement.height; });
    var waistVals = measurements.map(function(measurement) { return measurement.waist; });
    var chestVals = measurements.map(function(measurement) { return measurement.chest; });

    return {
      weight: findMean(weightVals),
      bodyfat: findMean(bodyfatVals),
      height: findMean(heightVals),
      waist: findMean(waistVals),
      chest: findMean(chestVals)
    };
  }

  function calculateMeasurementChange(firstMeasurements, secondMeasurements) {
    if (secondMeasurements) {
      return {
        weight:  (firstMeasurements.weight - secondMeasurements.weight),
        bodyfat: (firstMeasurements.bodyfat - secondMeasurements.bodyfat),
        height:  (firstMeasurements.height - secondMeasurements.height),
        waist: (firstMeasurements.waist - secondMeasurements.waist),
        chest:  (firstMeasurements.chest - secondMeasurements.chest)
      };
    }
    else {
      return {};
    }
  }

  ChapterStatsCtrl.firstEntryID = ChapterStatsCtrl.chapter.entries[ChapterStatsCtrl.chapter.entries.length - 1].id;
  ChapterStatsCtrl.firstMeasurement = ChapterStatsCtrl.chapter.measurements[ChapterStatsCtrl.chapter.measurements.length - 1] || {};
  var thisWeeksMeasurements = ChapterStatsCtrl.chapter.this_weeks_measurements.filter(notNull);
  var lastWeeksMeasurements = ChapterStatsCtrl.chapter.last_weeks_measurements.filter(notNull);

  ChapterStatsCtrl.thisWeekMeasurements = calculateWeeklyMeasurementAverages(thisWeeksMeasurements);
  ChapterStatsCtrl.lastWeekMeasurements = calculateWeeklyMeasurementAverages(lastWeeksMeasurements);

  ChapterStatsCtrl.measurementChange = calculateMeasurementChange(ChapterStatsCtrl.thisWeekMeasurements, ChapterStatsCtrl.lastWeekMeasurements);
  formatProperties(ChapterStatsCtrl.measurementChange, 1);

  // foods

  function calculateWeeklyIntakeAverages(foods, entryCount) {
    var calories = foods.map(function(food) { return food.calories });
    var protein = foods.map(function(food) { return food.protein});
    var carbs = foods.map(function(food) { return food.carbs });
    var fats = foods.map(function(food) { return food.fats });
    if (entryCount > 0) {
      return {
        calories: calories.reduce( (total, calories) => total + calories, 0)/entryCount,
        protein: protein.reduce( (total, protein) => total + protein, 0)/entryCount,
        carbs: carbs.reduce( (total, carbs) => total + carbs, 0)/entryCount,
        fats: fats.reduce( (total, fats) => total + fats, 0)/entryCount
      }
    } else {
      return {
        calories: undefined,
        protein: undefined,
        carbs: undefined,
        fats: undefined
      }
    }
  }

  function calculateIntakeChange(firstIntakes, secondIntakes) {
    return {
      calories: (firstIntakes.calories - secondIntakes.calories),
      protein: (firstIntakes.protein - secondIntakes.protein),
      carbs: (firstIntakes.carbs - secondIntakes.carbs),
      fats: (firstIntakes.fats - secondIntakes.fats)
    }
  }

  var thisWeeksFoods = thisWeeksEntries.map(function(entry) { return entry.foods }).reduce(function(allFoods, foods) { return allFoods.concat(foods) }, []);
  var lastWeeksFoods = lastWeeksEntries.map(function(entry) { return entry.foods }).reduce(function(allFoods, foods) { return allFoods.concat(foods) }, []);

  ChapterStatsCtrl.thisWeeksIntakes = calculateWeeklyIntakeAverages(thisWeeksFoods, thisWeeksEntries.length);
  ChapterStatsCtrl.lastWeeksIntakes = calculateWeeklyIntakeAverages(lastWeeksFoods, lastWeeksEntries.length);

  ChapterStatsCtrl.intakeChange = calculateIntakeChange(ChapterStatsCtrl.thisWeeksIntakes, ChapterStatsCtrl.lastWeeksIntakes);
  formatProperties(ChapterStatsCtrl.intakeChange, 0);

  // averages, helpers, formatters, etc.

  ChapterStatsCtrl.calculateAverage = function(total) {
    if (ChapterStatsCtrl.chapter.entries.length > 0) {
      return Math.round(total / ChapterStatsCtrl.chapter.entries.length)
    } else {
      return 0;
    }
  }

  function findMean(values) {
    var sum = 0;
    var count = 0;
    for (i = 0; i < values.length; i++) {
      if (values[i] !== null && values[i] !== undefined) {
        sum += values[i];
        count ++;
      }
    }
    if (count > 0) {
      return sum/count;
    } else {
      return undefined;
    }
  }

  function notNull(value) {
    return value !== null;
  }

  function formatProperties(object, fix) {
    for (var key in object) {
      if (object.hasOwnProperty(key)) {
        if (isNaN(object[key])) {
          object[key] = "N/A";
        } else {
          object[key] = object[key].toFixed(fix);
        }
      };
    }
  }

  if (ChapterStatsCtrl.chapter.completed_at !== null) {
    var daysPassed = Math.round((new Date(ChapterStatsCtrl.chapter.completed_at) - new Date(ChapterStatsCtrl.chapter.created_at)) / (60*60*24*1000));
  } else {
    var daysPassed = Math.round((new Date() - new Date(ChapterStatsCtrl.chapter.created_at)) / (60*60*24*1000));
  }
  if (daysPassed == 0) { daysPassed = 1; }

  ChapterStatsCtrl.averageChangeWeight = ((ChapterStatsCtrl.thisWeekMeasurements.weight - ChapterStatsCtrl.firstMeasurement.weight) * 7 / daysPassed).toFixed(2);
  if (ChapterStatsCtrl.averageChangeWeight === "NaN") { ChapterStatsCtrl.averageChangeWeight = "N/A" }

  ChapterStatsCtrl.estimatedTDE = ChapterStatsCtrl.averageChangeWeight * 500 + ChapterStatsCtrl.calculateAverage(ChapterStatsCtrl.chapter.total_calories) || "N/A";

}

angular
  .module('fitnessTracker')
    .controller('ChapterStatsController', ChapterStatsController);
<commit_msg>Update ChaperStatsCtrl to use info from server-side JSON for foods<commit_after>function ChapterStatsController(chapterJSON) {
  var ChapterStatsCtrl = this;
  ChapterStatsCtrl.chapter = chapterJSON.data;

  // entries

  function filterWeeklyEntries(startOfWeek, entries) {
    var endOfWeek = new Date();
    endOfWeek.setDate(startOfWeek.getDate() + 7);
    var weeksEntries = []
    for (i = 0; i < entries.length; i++) {
      var entryDay = new Date(entries[i].day);
      if (entryDay > startOfWeek && entryDay <= endOfWeek) {
        weeksEntries.push(entries[i]);
      }
    }
    return weeksEntries;
  }

  if (ChapterStatsCtrl.chapter.completed_at !== null) {
    var startOfThisWeek = new Date(ChapterStatsCtrl.chapter.completed_at);
    var startOfLastWeek = new Date(ChapterStatsCtrl.chapter.completed_at);
  } else {
    var startOfThisWeek = new Date();
    var startOfLastWeek = new Date();
  }

  startOfThisWeek.setDate(startOfThisWeek.getDate() - 7)
  startOfLastWeek.setDate(startOfLastWeek.getDate() - 14)

  var thisWeeksEntries = filterWeeklyEntries(startOfThisWeek, ChapterStatsCtrl.chapter.entries.slice(0, 7));
  var lastWeeksEntries = filterWeeklyEntries(startOfLastWeek, ChapterStatsCtrl.chapter.entries.slice(0, 14));

  console.log(ChapterStatsCtrl.chapter.this_weeks_measurements);
  console.log(thisWeeksEntries);
  console.log(ChapterStatsCtrl.chapter.last_weeks_measurements)
  console.log(lastWeeksEntries);

  // measurements

  function calculateWeeklyMeasurementAverages(measurements) {
    var weightVals = measurements.map(function(measurement) { return measurement.weight});
    var bodyfatVals = measurements.map(function(measurement) { return measurement.bodyfat; });
    var heightVals = measurements.map(function(measurement) { return measurement.height; });
    var waistVals = measurements.map(function(measurement) { return measurement.waist; });
    var chestVals = measurements.map(function(measurement) { return measurement.chest; });

    return {
      weight: findMean(weightVals),
      bodyfat: findMean(bodyfatVals),
      height: findMean(heightVals),
      waist: findMean(waistVals),
      chest: findMean(chestVals)
    };
  }

  function calculateMeasurementChange(firstMeasurements, secondMeasurements) {
    if (secondMeasurements) {
      return {
        weight:  (firstMeasurements.weight - secondMeasurements.weight),
        bodyfat: (firstMeasurements.bodyfat - secondMeasurements.bodyfat),
        height:  (firstMeasurements.height - secondMeasurements.height),
        waist: (firstMeasurements.waist - secondMeasurements.waist),
        chest:  (firstMeasurements.chest - secondMeasurements.chest)
      };
    }
    else {
      return {};
    }
  }

  ChapterStatsCtrl.firstEntryID = ChapterStatsCtrl.chapter.entries[ChapterStatsCtrl.chapter.entries.length - 1].id;
  ChapterStatsCtrl.firstMeasurement = ChapterStatsCtrl.chapter.measurements[ChapterStatsCtrl.chapter.measurements.length - 1] || {};
  var thisWeeksMeasurements = ChapterStatsCtrl.chapter.this_weeks_measurements.filter(notNull);
  var lastWeeksMeasurements = ChapterStatsCtrl.chapter.last_weeks_measurements.filter(notNull);

  ChapterStatsCtrl.thisWeekMeasurements = calculateWeeklyMeasurementAverages(thisWeeksMeasurements);
  ChapterStatsCtrl.lastWeekMeasurements = calculateWeeklyMeasurementAverages(lastWeeksMeasurements);

  ChapterStatsCtrl.measurementChange = calculateMeasurementChange(ChapterStatsCtrl.thisWeekMeasurements, ChapterStatsCtrl.lastWeekMeasurements);
  formatProperties(ChapterStatsCtrl.measurementChange, 1);

  // foods

  function calculateWeeklyIntakeAverages(foods, entryCount) {
    var calories = foods.map(function(food) { return food.calories });
    var protein = foods.map(function(food) { return food.protein});
    var carbs = foods.map(function(food) { return food.carbs });
    var fats = foods.map(function(food) { return food.fats });
    if (entryCount > 0) {
      return {
        calories: calories.reduce( (total, calories) => total + calories, 0)/entryCount,
        protein: protein.reduce( (total, protein) => total + protein, 0)/entryCount,
        carbs: carbs.reduce( (total, carbs) => total + carbs, 0)/entryCount,
        fats: fats.reduce( (total, fats) => total + fats, 0)/entryCount
      }
    } else {
      return {
        calories: undefined,
        protein: undefined,
        carbs: undefined,
        fats: undefined
      }
    }
  }

  function calculateIntakeChange(firstIntakes, secondIntakes) {
    return {
      calories: (firstIntakes.calories - secondIntakes.calories),
      protein: (firstIntakes.protein - secondIntakes.protein),
      carbs: (firstIntakes.carbs - secondIntakes.carbs),
      fats: (firstIntakes.fats - secondIntakes.fats)
    }
  }

  var thisWeeksEntryLength = ChapterStatsCtrl.chapter.this_weeks_foods.length;
  var lastWeeksEntryLength = ChapterStatsCtrl.chapter.last_weeks_foods.length;

  var thisWeeksFoods = ChapterStatsCtrl.chapter.this_weeks_foods.reduce(function(allFoods, foods) { return allFoods.concat(foods) }, []);
  var lastWeeksFoods = ChapterStatsCtrl.chapter.last_weeks_foods.reduce(function(allFoods, foods) { return allFoods.concat(foods) }, []);

  ChapterStatsCtrl.thisWeeksIntakes = calculateWeeklyIntakeAverages(thisWeeksFoods, thisWeeksEntryLength);
  ChapterStatsCtrl.lastWeeksIntakes = calculateWeeklyIntakeAverages(lastWeeksFoods, lastWeeksEntryLength);

  ChapterStatsCtrl.intakeChange = calculateIntakeChange(ChapterStatsCtrl.thisWeeksIntakes, ChapterStatsCtrl.lastWeeksIntakes);
  formatProperties(ChapterStatsCtrl.intakeChange, 0);

  // averages, helpers, formatters, etc.

  ChapterStatsCtrl.calculateAverage = function(total) {
    if (ChapterStatsCtrl.chapter.entries.length > 0) {
      return Math.round(total / ChapterStatsCtrl.chapter.entries.length)
    } else {
      return 0;
    }
  }

  function findMean(values) {
    var sum = 0;
    var count = 0;
    for (i = 0; i < values.length; i++) {
      if (values[i] !== null && values[i] !== undefined) {
        sum += values[i];
        count ++;
      }
    }
    if (count > 0) {
      return sum/count;
    } else {
      return undefined;
    }
  }

  function notNull(value) {
    return value !== null;
  }

  function formatProperties(object, fix) {
    for (var key in object) {
      if (object.hasOwnProperty(key)) {
        if (isNaN(object[key])) {
          object[key] = "N/A";
        } else {
          object[key] = object[key].toFixed(fix);
        }
      };
    }
  }

  if (ChapterStatsCtrl.chapter.completed_at !== null) {
    var daysPassed = Math.round((new Date(ChapterStatsCtrl.chapter.completed_at) - new Date(ChapterStatsCtrl.chapter.created_at)) / (60*60*24*1000));
  } else {
    var daysPassed = Math.round((new Date() - new Date(ChapterStatsCtrl.chapter.created_at)) / (60*60*24*1000));
  }
  if (daysPassed == 0) { daysPassed = 1; }

  ChapterStatsCtrl.averageChangeWeight = ((ChapterStatsCtrl.thisWeekMeasurements.weight - ChapterStatsCtrl.firstMeasurement.weight) * 7 / daysPassed).toFixed(2);
  if (ChapterStatsCtrl.averageChangeWeight === "NaN") { ChapterStatsCtrl.averageChangeWeight = "N/A" }

  ChapterStatsCtrl.estimatedTDE = ChapterStatsCtrl.averageChangeWeight * 500 + ChapterStatsCtrl.calculateAverage(ChapterStatsCtrl.chapter.total_calories) || "N/A";

}

angular
  .module('fitnessTracker')
    .controller('ChapterStatsController', ChapterStatsController);
<|endoftext|>


<commit_before>(function ContextMenu($angular) {

    "use strict";

    /**
     * @module ngContextMenu
     * @author Adam Timberlake
     * @link https://github.com/Wildhoney/ngContextMenu
     */
    var module = $angular.module('ngContextMenu', []);

    /**
     * @module ngContextMenu
     * @service ContextMenu
     * @author Adam Timberlake
     * @link https://github.com/Wildhoney/ngContextMenu
     */
    module.factory('contextMenu', function contextMenuService() {

        var factory = {};

        /**
         * @property cancelIteration
         * @type {Number}
         * @default 0
         */
        factory.cancelIteration = 1;

        /**
         * @property isOpening
         * @type {Boolean}
         */
        factory.isOpening = false;

        /**
         * @property attachedClick
         * @type {Boolean}
         */
        factory.attachedClick = false;

        /**
         * Responsible for closing all of the visible context menus.
         *
         * @method cancelAll
         * @return {void}
         */
        factory.cancelAll = function cancelAll() {
            factory.cancelIteration++;
        };

        return factory;

    });

    /**
     * @module ngContextMenu
     * @directive contextMenu
     * @author Adam Timberlake
     * @link https://github.com/Wildhoney/ngContextMenu
     */
    module.directive('contextMenu', ['$window', '$http', '$interpolate', '$compile', '$templateCache', 'contextMenu',

    function contextMenuDirective($window, $http, $interpolate, $compile, $templateCache, contextMenu) {

        return {

            /**
             * @property restrict
             * @type {String}
             */
            restrict: 'EA',

            /**
             * @property require
             * @type {String}
             */
            require: '?ngModel',

            /**
             * @property scope
             * @type {Object}
             */
            scope: {
                include: '@contextMenu',
                model: '=ngModel'
            },

            /**
             * @method controller
             * @param $scope {Object}
             * @return {void}
             */
            controller: ['$scope', function controller($scope) {

                /**
                 * @property template
                 * @type {String}
                 */
                $scope.template = '';

                /**
                 * @property event
                 * @type {Object|null}
                 */
                $scope.event = null;

                /**
                 * @property menu
                 * @type {Object|null}
                 */
                $scope.menu = null;

                /**
                 * @method throwException
                 * @throw Exception
                 * @param message {String}
                 * @return {void}
                 */
                $scope.throwException = function throwException(message) {
                    throw "ngContextMenu: " + message + ".";
                };

                /**
                 * @method cacheTemplate
                 * @param templatePath {String}
                 * @return {void}
                 */
                $scope.cacheTemplate = function cacheTemplate(templatePath) {

                    $http.get(templatePath, { cache: $templateCache }).then(function then(response) {

                        // Define the template with expressions.
                        $scope.template = response.data;

                    }).catch(function catchError() {

                        // Unable to find the supplied template path.
                        $scope.throwException('Invalid context menu path: "' + templatePath + '"');

                    });

                };

                /**
                 * @method cancelOne
                 * @return {void}
                 */
                $scope.cancelOne = function cancelOne() {

                    if ($scope.menu) {
                        $scope.menu.remove();
                        $scope.event = null;
                    }

                };

            }],

            /**
             * @method link
             * @param scope {Object}
             * @param element {Object}
             * @param attributes {Object}
             * @return {void}
             */
            link: function link(scope, element, attributes) {

                if (!contextMenu.attachedClick) {

                    // Subscribe to the onClick event of the HTML node to remove any context menus
                    // that may be open.
                    var htmlElement = $angular.element($window.document.getElementsByTagName('html'));
                    contextMenu.attachedClick = true;

                    htmlElement.bind('click', function onClick() {

                        if (attributes.contextEvent === 'click' && contextMenu.isOpening) {
                            contextMenu.isOpening = false;
                            return;
                        }

                        // Remove all of the open context menus.
                        scope.$apply(contextMenu.cancelAll);

                    });

                }

                // Evaluate the supplied template against the model.
                scope.cacheTemplate(scope.include, scope.model || {});

                // Listen for any attempts to cancel the current context menu.
                scope.$watch(function setupObserver() {
                    return contextMenu.cancelIteration;
                }, scope.cancelOne);

                /**
                 * @method render
                 * @param event {Object}
                 * @return {void}
                 */
                scope.render = function render(event) {

                    if (!event) {
                        return;
                    }

                    // Prevent the default context menu from opening, and make the user
                    // defined context menu appear instead.
                    event.preventDefault();

                    var interpolated     = $interpolate(scope.template)(scope.model || {}),
                        template         = $angular.element(interpolated),
                        compiledTemplate = $compile(template)($angular.extend(scope.$parent, scope.model));

                    if (compiledTemplate.length > 1) {

                        // Throw exception when the compiled template is adding more than one child node.
                        scope.throwException('Context menu is adding ' + compiledTemplate.length + ' child nodes');

                    }

                    element.append(compiledTemplate);

                    // Keep a track of the added context menu for removing it if necessary.
                    var nativeElement = element[0],
                        childCount    = nativeElement.childNodes.length;

                    // Update the position of the newly added context menu.
                    scope.menu    = $angular.element(nativeElement.childNodes[childCount - 1]);
                    var translate = 'translate(' + event.clientX + 'px, ' + event.clientY + 'px)';
                    scope.menu.css({ transform: translate });

                    // Memorise the event for re-rendering.
                    scope.event = event;

                };

                // Bind to the context menu event.
                element.bind(attributes.contextEvent || 'contextmenu', function onContextMenu(event) {

                    event.stopPropagation();

                    scope.$apply(function apply() {

                        // Remove any existing context menus for this element and other elements.
                        contextMenu.cancelAll();

                    });

                    scope.render(event);
                    contextMenu.isOpening = true;

                });

                if (scope.model) {

                    scope.$watch('model', function modelChanged() {

                        // Re-render the context menu if necessary.
                        var event = scope.event;
                        scope.cancelOne();
                        scope.render(event);

                    }, true);

                }

            }

        }

    }]);

})(window.angular);<commit_msg>Taking into account ng-controller<commit_after>(function ContextMenu($angular) {

    "use strict";

    /**
     * @module ngContextMenu
     * @author Adam Timberlake
     * @link https://github.com/Wildhoney/ngContextMenu
     */
    var module = $angular.module('ngContextMenu', []);

    /**
     * @module ngContextMenu
     * @service ContextMenu
     * @author Adam Timberlake
     * @link https://github.com/Wildhoney/ngContextMenu
     */
    module.factory('contextMenu', function contextMenuService() {

        var factory = {};

        /**
         * @property cancelIteration
         * @type {Number}
         * @default 0
         */
        factory.cancelIteration = 1;

        /**
         * @property isOpening
         * @type {Boolean}
         */
        factory.isOpening = false;

        /**
         * @property attachedClick
         * @type {Boolean}
         */
        factory.attachedClick = false;

        /**
         * Responsible for closing all of the visible context menus.
         *
         * @method cancelAll
         * @return {void}
         */
        factory.cancelAll = function cancelAll() {
            factory.cancelIteration++;
        };

        return factory;

    });

    /**
     * @module ngContextMenu
     * @directive contextMenu
     * @author Adam Timberlake
     * @link https://github.com/Wildhoney/ngContextMenu
     */
    module.directive('contextMenu', ['$window', '$http', '$interpolate', '$compile', '$templateCache', 'contextMenu',

        function contextMenuDirective($window, $http, $interpolate, $compile, $templateCache, contextMenu) {

            return {

                /**
                 * @property restrict
                 * @type {String}
                 */
                restrict: 'EA',

                /**
                 * @property require
                 * @type {String}
                 */
                require: '?ngModel',

                /**
                 * @property scope
                 * @type {Object}
                 */
                scope: {
                    include: '@contextMenu',
                    model: '=ngModel'
                },

                /**
                 * @method controller
                 * @param $scope {Object}
                 * @return {void}
                 */
                controller: ['$scope', function controller($scope) {

                    /**
                     * @property template
                     * @type {String}
                     */
                    $scope.template = '';

                    /**
                     * @property event
                     * @type {Object|null}
                     */
                    $scope.event = null;

                    /**
                     * @property menu
                     * @type {Object|null}
                     */
                    $scope.menu = null;

                    /**
                     * @method throwException
                     * @throw Exception
                     * @param message {String}
                     * @return {void}
                     */
                    $scope.throwException = function throwException(message) {
                        throw "ngContextMenu: " + message + ".";
                    };

                    /**
                     * @method cacheTemplate
                     * @param templatePath {String}
                     * @return {void}
                     */
                    $scope.cacheTemplate = function cacheTemplate(templatePath) {

                        $http.get(templatePath, { cache: $templateCache }).then(function then(response) {

                            // Define the template with expressions.
                            $scope.template = response.data;

                        }).catch(function catchError() {

                            // Unable to find the supplied template path.
                            $scope.throwException('Invalid context menu path: "' + templatePath + '"');

                        });

                    };

                    /**
                     * @method cancelOne
                     * @return {void}
                     */
                    $scope.cancelOne = function cancelOne() {

                        if ($scope.menu) {
                            $scope.menu.remove();
                            $scope.event = null;
                        }

                    };

                }],

                /**
                 * @method link
                 * @param scope {Object}
                 * @param element {Object}
                 * @param attributes {Object}
                 * @return {void}
                 */
                link: function link(scope, element, attributes) {

                    if (!contextMenu.attachedClick) {

                        // Subscribe to the onClick event of the HTML node to remove any context menus
                        // that may be open.
                        var htmlElement = $angular.element($window.document.getElementsByTagName('html'));
                        contextMenu.attachedClick = true;

                        htmlElement.bind('click', function onClick() {

                            if (attributes.contextEvent === 'click' && contextMenu.isOpening) {
                                contextMenu.isOpening = false;
                                return;
                            }

                            // Remove all of the open context menus.
                            scope.$apply(contextMenu.cancelAll);

                        });

                    }

                    // Evaluate the supplied template against the model.
                    scope.cacheTemplate(scope.include, scope.model || {});

                    // Listen for any attempts to cancel the current context menu.
                    scope.$watch(function setupObserver() {
                        return contextMenu.cancelIteration;
                    }, scope.cancelOne);

                    /**
                     * @method render
                     * @param event {Object}
                     * @return {void}
                     */
                    scope.render = function render(event) {

                        if (!event) {
                            return;
                        }

                        // Prevent the default context menu from opening, and make the user
                        // defined context menu appear instead.
                        event.preventDefault();

                        var extendedScope = scope.model;

                        console.log(extendedScope);

                        Object.keys(scope.$parent).forEach(function forEach(key) {

                            if (!key.match(/^\$/) && key !== 'this') {
                                extendedScope[key] = scope.$parent[key];
                            }

                        });

                        var interpolated     = $interpolate(scope.template)(scope.model),
                            template         = $angular.element(interpolated),
                            compiledTemplate = $compile(template)($angular.extend(scope.$parent, scope.model));

                        if (compiledTemplate.length > 1) {

                            // Throw exception when the compiled template is adding more than one child node.
                            scope.throwException('Context menu is adding ' + compiledTemplate.length + ' child nodes');

                        }

                        element.append(compiledTemplate);

                        // Keep a track of the added context menu for removing it if necessary.
                        var nativeElement = element[0],
                            childCount    = nativeElement.childNodes.length;

                        // Update the position of the newly added context menu.
                        scope.menu    = $angular.element(nativeElement.childNodes[childCount - 1]);
                        var translate = 'translate(' + event.clientX + 'px, ' + event.clientY + 'px)';
                        scope.menu.css({ transform: translate });

                        // Memorise the event for re-rendering.
                        scope.event = event;

                    };

                    // Bind to the context menu event.
                    element.bind(attributes.contextEvent || 'contextmenu', function onContextMenu(event) {

                        event.stopPropagation();

                        scope.$apply(function apply() {

                            // Remove any existing context menus for this element and other elements.
                            contextMenu.cancelAll();

                        });

                        scope.render(event);
                        contextMenu.isOpening = true;

                    });

                    if (scope.model) {

                        scope.$watch('model', function modelChanged() {

                            // Re-render the context menu if necessary.
                            var event = scope.event;
                            scope.cancelOne();
                            scope.render(event);

                        }, true);

                    }

                }

            }

        }]);

})(window.angular);<|endoftext|>


<commit_before>var util = require('./config/grunt/utils.js');

module.exports = function(grunt){
   var APP_VERSION = util.getVersion();
  // Project Configuration
	grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    karma: {
      options: {
          singleRun: true
      },
			unit: {
				configFile: 'config/karma.conf.js'
			}
		},
    concat: {
      options: {
          separator: '\n',
          process: function(src){
              return src
                  .replace(/%VERSION%/g, APP_VERSION.full)
                  .replace(/%WEBSITE%/g, APP_VERSION.website)
                  .replace(/%LICENSE%/g, APP_VERSION.license)
                  .replace(/%CONTRIBUTOR%/g, APP_VERSION.contributor)
                  .replace(/%APP_NAME%/g, APP_VERSION.appname)
                  .replace(/%DESCRIPTION%/g, APP_VERSION.description);
          }
      },
      module:{
          src: [
                  'src/header.js',
                  'src/angular-utilz.js'
               ],
          dest: 'dist/angular-utilz.js'
      },
      minify:{
          src: [
                  'src/header.js',
                  'dist/angular-utilz.min.js'
               ],
          dest: 'dist/angular-utilz.min.js'
      }
    },
    uglify: {
      options: {
        mangle: true
      },
      module: {
        files: {
          'dist/angular-utilz.min.js': ['dist/angular-utilz.js']
        }
      }
    },
    bump: {
      options: {
        files: ['package.json', 'bower.json'],
        updateConfigs: [],
        commit: false,
        commitMessage: 'Release v%VERSION%',
        commitFiles: ['package.json'],
        createTag: false,
        tagName: '%VERSION%',
        tagMessage: 'Version %VERSION%',
        push: false,
        pushTo: APP_VERSION.website,
        gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d'
      }
    },
    gta: {
        add: {
            command: 'add -A .',
            options: {
                stdout: true
            }
        },
        commit: {
            command: 'commit -am "Release version '+ APP_VERSION.full +' "',
            options: {
                stdout: true
            }
        },
        tag: {
            command:('tag ' + APP_VERSION.full),
            options: {
                stdout: true
            }
        },
        push: {
            command:('push --tags ' ),
            options: {
                stdout: true
            }
        }
    },

  });

  require('load-grunt-tasks')(grunt);

  grunt.registerTask('test', ['karma:unit']);
  grunt.registerTask('release', ['gta:add', 'gta:commit', 'gta:tag', 'gta:push']);

  grunt.registerTask('build', ['test', 'concat:module', 'uglify:module', 'concat:minify','bump:prerelease']);
  grunt.registerTask('default', ['test']);
};
<commit_msg>cleanup gruntfile<commit_after>var util = require('./config/grunt/utils.js');

module.exports = function(grunt){
   var APP_VERSION = util.getVersion();
  // Project Configuration
	grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    karma: {
      options: {
          singleRun: true
      },
			unit: {
				configFile: 'config/karma.conf.js'
			}
		},
    concat: {
      options: {
          separator: '\n',
          process: function(src){
              return src
                  .replace(/%VERSION%/g, APP_VERSION.full)
                  .replace(/%WEBSITE%/g, APP_VERSION.website)
                  .replace(/%LICENSE%/g, APP_VERSION.license)
                  .replace(/%CONTRIBUTOR%/g, APP_VERSION.contributor)
                  .replace(/%APP_NAME%/g, APP_VERSION.appname)
                  .replace(/%DESCRIPTION%/g, APP_VERSION.description);
          }
      },
      module:{
          src: [
                  'src/header.js',
                  'src/angular-utilz.js'
               ],
          dest: 'dist/angular-utilz.js'
      },
      minify:{
          src: [
                  'src/header.js',
                  'dist/angular-utilz.min.js'
               ],
          dest: 'dist/angular-utilz.min.js'
      }
    },
    uglify: {
      options: {
        mangle: true
      },
      module: {
        files: {
          'dist/angular-utilz.min.js': ['dist/angular-utilz.js']
        }
      }
    },
    bump: {
      options: {
        files: ['package.json', 'bower.json'],
        updateConfigs: [],
        commit: false,
        commitMessage: 'Release v%VERSION%',
        commitFiles: ['package.json'],
        createTag: false,
        tagName: '%VERSION%',
        tagMessage: 'Version %VERSION%',
        push: false,
        pushTo: APP_VERSION.website,
        gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d'
      }
    },
    gta: {
        add: {
            command: 'add -A .',
            options: {
                stdout: true
            }
        },
        commit: {
            command: 'commit -am "Release version '+ APP_VERSION.full +' "',
            options: {
                stdout: true
            }
        },
        tag: {
            command:('tag ' + APP_VERSION.full),
            options: {
                stdout: true
            }
        },
        push: {
            command:('push --tags ' ),
            options: {
                stdout: true
            }
        }
    },

  });

  require('load-grunt-tasks')(grunt);

  grunt.registerTask('test', ['karma:unit']);
  grunt.registerTask('release', ['gta:add', 'gta:commit', 'gta:tag', 'gta:push']);
  grunt.registerTask('build', ['test', 'concat:module', 'uglify:module', 'concat:minify','bump:prerelease']);
  grunt.registerTask('default', ['test']);
};
<|endoftext|>


<commit_before>import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import { useRouteMatch } from 'react-router-dom';
import mapbox from 'mapbox-gl';

import {
  circleOpacity,
  circleBlur,
  coloredCircleRadius,
  borderCircleRadius,
  coloredSquareSize,
  borderSquareSize,
} from '../../utils/map-settings';
import { getFillExpression } from '../../utils/colors';
import Popover from './popover';
import { square } from './square';

export default function MeasurementsLayer({
  activeParameter,
  country,
  map,
  sourceId,
}) {
  let match = useRouteMatch();

  const countryFilter = ['==', ['get', 'country'], country];
  const circlesFilter = ['==', ['get', 'isMobile'], false];
  const squaresFilter = ['==', ['get', 'isMobile'], true];

  const circlesCountryFilter = ['all', countryFilter, circlesFilter];
  const squaresCountryFilter = ['all', countryFilter, squaresFilter];

  useEffect(() => {
    if (!map.hasImage('square')) map.addImage('square', square, { sdf: true });
    map.addLayer({
      id: `${activeParameter}-square-outline`,
      source: sourceId,
      'source-layer': 'default',
      type: 'symbol',
      paint: {
        'icon-color': getFillExpression(activeParameter, 'dark'),
      },
      layout: {
        'icon-image': 'square',
        'icon-size': borderSquareSize,
        'icon-allow-overlap': true,
      },
      filter: squaresFilter,
    });

    map.addLayer({
      id: `${activeParameter}-squares`,
      source: sourceId,
      'source-layer': 'default',
      type: 'symbol',
      paint: {
        'icon-color': getFillExpression(activeParameter),
      },
      layout: {
        'icon-image': 'square',
        'icon-size': coloredSquareSize,
        'icon-allow-overlap': true,
      },
      filter: squaresFilter,
    });

    map.addLayer({
      id: `${activeParameter}-circle-outline`,
      source: sourceId,
      'source-layer': 'default',
      type: 'circle',
      paint: {
        'circle-color': getFillExpression(activeParameter, 'dark'),
        'circle-opacity': 1,
        'circle-radius': borderCircleRadius,
        'circle-blur': 0,
      },
      filter: circlesFilter,
    });

    map.addLayer({
      id: `${activeParameter}-circles`,
      source: sourceId,
      'source-layer': 'default',
      type: 'circle',
      paint: {
        'circle-color': getFillExpression(activeParameter),
        'circle-opacity': circleOpacity,
        'circle-radius': coloredCircleRadius,
        'circle-blur': circleBlur,
      },
      filter: circlesFilter,
    });

    // Change the cursor to a pointer when the mouse is over the layer.
    map.on('mouseenter', `${activeParameter}-circles`, function () {
      map.getCanvas().style.cursor = 'pointer';
    });
    map.on('mouseenter', `${activeParameter}-squares`, function () {
      map.getCanvas().style.cursor = 'pointer';
    });

    // Change it back to a pointer when it leaves.
    map.on('mouseleave', `${activeParameter}-circles`, function () {
      map.getCanvas().style.cursor = '';
    });
    map.on('mouseleave', `${activeParameter}-squares`, function () {
      map.getCanvas().style.cursor = '';
    });

    const openPopup = e => {
      const coordinates = e.features[0].geometry.coordinates.slice();

      // Ensure that if the map is zoomed out such that multiple
      // copies of the feature are visible, the popup appears
      // over the copy being pointed to.
      while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
        coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
      }

      let popoverElement = document.createElement('div');
      ReactDOM.render(
        <Popover
          activeParameter={activeParameter}
          locationId={e.features[0].properties.locationId}
          currentPage={parseInt(match.params.id, 10)}
        />,
        popoverElement
      );
      new mapbox.Popup()
        .setLngLat(coordinates)
        .setDOMContent(popoverElement)
        .addTo(map);
    };

    map.on('click', `${activeParameter}-circles`, openPopup);
    map.on('click', `${activeParameter}-squares`, openPopup);

    return () => {
      if (map.getLayer(`${activeParameter}-squares`))
        map.removeLayer(`${activeParameter}-squares`);
      if (map.getLayer(`${activeParameter}-square-outline`))
        map.removeLayer(`${activeParameter}-square-outline`);
      if (map.getLayer(`${activeParameter}-circles`))
        map.removeLayer(`${activeParameter}-circles`);
      if (map.getLayer(`${activeParameter}-circle-outline`))
        map.removeLayer(`${activeParameter}-circle-outline`);
    };
  }, [sourceId, activeParameter]);

  useEffect(() => {
    if (country && map.getLayer(`${activeParameter}-circles`)) {
      map.setFilter(`${activeParameter}-square-outline`, squaresCountryFilter);
      map.setFilter(`${activeParameter}-squares`, squaresCountryFilter);
      map.setFilter(`${activeParameter}-circle-outline`, circlesCountryFilter);
      map.setFilter(`${activeParameter}-circles`, circlesCountryFilter);
    }
    return () => {
      if (map.getLayer(`${activeParameter}-square-outline`))
        map.setFilter(`${activeParameter}-square-outline`, squaresFilter);
      if (map.getLayer(`${activeParameter}-squares`))
        map.setFilter(`${activeParameter}-squares`, squaresFilter);
      if (map.getLayer(`${activeParameter}-circle-outline`))
        map.setFilter(`${activeParameter}-circle-outline`, circlesFilter);
      if (map.getLayer(`${activeParameter}-circles`))
        map.setFilter(`${activeParameter}-circles`, circlesFilter);
    };
  }, [country]);

  return null;
}

MeasurementsLayer.propTypes = {
  activeParameter: PropTypes.number.isRequired,
  country: PropTypes.string,
  sourceId: PropTypes.string,
  map: PropTypes.object,
};
<commit_msg>Update filter criteria for measurement symbols<commit_after>import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import { useRouteMatch } from 'react-router-dom';
import mapbox from 'mapbox-gl';

import {
  circleOpacity,
  circleBlur,
  coloredCircleRadius,
  borderCircleRadius,
  coloredSquareSize,
  borderSquareSize,
} from '../../utils/map-settings';
import { getFillExpression } from '../../utils/colors';
import Popover from './popover';
import { square } from './square';

export default function MeasurementsLayer({
  activeParameter,
  country,
  map,
  sourceId,
}) {
  let match = useRouteMatch();

  const countryFilter = ['==', ['get', 'country'], country];
  const circlesFilter = ['==', ['get', 'sensorType'], 'reference'];
  const squaresFilter = ['==', ['get', 'sensorType'], 'low-cost sensor'];

  const circlesCountryFilter = ['all', countryFilter, circlesFilter];
  const squaresCountryFilter = ['all', countryFilter, squaresFilter];

  useEffect(() => {
    if (!map.hasImage('square')) map.addImage('square', square, { sdf: true });
    map.addLayer({
      id: `${activeParameter}-square-outline`,
      source: sourceId,
      'source-layer': 'default',
      type: 'symbol',
      paint: {
        'icon-color': getFillExpression(activeParameter, 'dark'),
      },
      layout: {
        'icon-image': 'square',
        'icon-size': borderSquareSize,
        'icon-allow-overlap': true,
      },
      filter: squaresFilter,
    });

    map.addLayer({
      id: `${activeParameter}-squares`,
      source: sourceId,
      'source-layer': 'default',
      type: 'symbol',
      paint: {
        'icon-color': getFillExpression(activeParameter),
      },
      layout: {
        'icon-image': 'square',
        'icon-size': coloredSquareSize,
        'icon-allow-overlap': true,
      },
      filter: squaresFilter,
    });

    map.addLayer({
      id: `${activeParameter}-circle-outline`,
      source: sourceId,
      'source-layer': 'default',
      type: 'circle',
      paint: {
        'circle-color': getFillExpression(activeParameter, 'dark'),
        'circle-opacity': 1,
        'circle-radius': borderCircleRadius,
        'circle-blur': 0,
      },
      filter: circlesFilter,
    });

    map.addLayer({
      id: `${activeParameter}-circles`,
      source: sourceId,
      'source-layer': 'default',
      type: 'circle',
      paint: {
        'circle-color': getFillExpression(activeParameter),
        'circle-opacity': circleOpacity,
        'circle-radius': coloredCircleRadius,
        'circle-blur': circleBlur,
      },
      filter: circlesFilter,
    });

    // Change the cursor to a pointer when the mouse is over the layer.
    map.on('mouseenter', `${activeParameter}-circles`, function () {
      map.getCanvas().style.cursor = 'pointer';
    });
    map.on('mouseenter', `${activeParameter}-squares`, function () {
      map.getCanvas().style.cursor = 'pointer';
    });

    // Change it back to a pointer when it leaves.
    map.on('mouseleave', `${activeParameter}-circles`, function () {
      map.getCanvas().style.cursor = '';
    });
    map.on('mouseleave', `${activeParameter}-squares`, function () {
      map.getCanvas().style.cursor = '';
    });

    const openPopup = e => {
      const coordinates = e.features[0].geometry.coordinates.slice();

      // Ensure that if the map is zoomed out such that multiple
      // copies of the feature are visible, the popup appears
      // over the copy being pointed to.
      while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
        coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
      }

      let popoverElement = document.createElement('div');
      ReactDOM.render(
        <Popover
          activeParameter={activeParameter}
          locationId={e.features[0].properties.locationId}
          currentPage={parseInt(match.params.id, 10)}
        />,
        popoverElement
      );
      new mapbox.Popup()
        .setLngLat(coordinates)
        .setDOMContent(popoverElement)
        .addTo(map);
    };

    map.on('click', `${activeParameter}-circles`, openPopup);
    map.on('click', `${activeParameter}-squares`, openPopup);

    return () => {
      if (map.getLayer(`${activeParameter}-squares`))
        map.removeLayer(`${activeParameter}-squares`);
      if (map.getLayer(`${activeParameter}-square-outline`))
        map.removeLayer(`${activeParameter}-square-outline`);
      if (map.getLayer(`${activeParameter}-circles`))
        map.removeLayer(`${activeParameter}-circles`);
      if (map.getLayer(`${activeParameter}-circle-outline`))
        map.removeLayer(`${activeParameter}-circle-outline`);
    };
  }, [sourceId, activeParameter]);

  useEffect(() => {
    if (country && map.getLayer(`${activeParameter}-circles`)) {
      map.setFilter(`${activeParameter}-square-outline`, squaresCountryFilter);
      map.setFilter(`${activeParameter}-squares`, squaresCountryFilter);
      map.setFilter(`${activeParameter}-circle-outline`, circlesCountryFilter);
      map.setFilter(`${activeParameter}-circles`, circlesCountryFilter);
    }
    return () => {
      if (map.getLayer(`${activeParameter}-square-outline`))
        map.setFilter(`${activeParameter}-square-outline`, squaresFilter);
      if (map.getLayer(`${activeParameter}-squares`))
        map.setFilter(`${activeParameter}-squares`, squaresFilter);
      if (map.getLayer(`${activeParameter}-circle-outline`))
        map.setFilter(`${activeParameter}-circle-outline`, circlesFilter);
      if (map.getLayer(`${activeParameter}-circles`))
        map.setFilter(`${activeParameter}-circles`, circlesFilter);
    };
  }, [country]);

  return null;
}

MeasurementsLayer.propTypes = {
  activeParameter: PropTypes.number.isRequired,
  country: PropTypes.string,
  sourceId: PropTypes.string,
  map: PropTypes.object,
};
<|endoftext|>


<commit_before>/**
 * @author Kuitos
 * @homepage https://github.com/kuitos/
 * @since 2015-11-03
 */
var fs = require('fs');
var path = require('path');
var indexHtml = fs.readFileSync(path.resolve(__dirname, "./src/index.html"), "utf-8");
var assets = require('./build/assets.json');

var interpolator = {

	js: {
		regex: /<!--\s*build:js\s*-->/,
		inlineTag: 'script',
		outerTag: '<script src="{{js}}"></script>'
	},

	css: {
		regex: /<!--\s*build:css\s*-->/,
		inlineTag: 'style',
		outerTag: '<link rel="stylesheet" href="{{css}}">'
	}

};

var isInlineAssets = process.argv.some(function (argv) {
	return argv === '--inline-source';
});

['script', 'link', 'style'].forEach(tag => {
	indexHtml = indexHtml.replace(new RegExp(`<${tag}.*>.*</${tag}>`, 'g'), '');
});

if (isInlineAssets) {

	Object.keys(interpolator).forEach(type => {

		var sourcePath = assets.app[type],
			info;

		if (sourcePath) {

			info = interpolator[type];
			indexHtml = indexHtml.replace(info.regex, `<${info.inlineTag}>` + fs.readFileSync(path.resolve(__dirname,
					`.${assets.app[type]}`), 'utf-8') + `</${info.inlineTag}>`);
		}

	});

} else {

	Object.keys(interpolator).forEach(type => {

		var sourcePath = assets.app[type],
			info;

		if (sourcePath) {
			info = interpolator[type];
			indexHtml = indexHtml.replace(info.regex, info.outerTag.replace(`{{${type}}}`, assets.app[type]));
		}

	});

}

fs.writeFile(path.resolve(__dirname, './index.html'), indexHtml, 'utf-8');
<commit_msg>delete deploy<commit_after><|endoftext|>


<commit_before>const chalk = require('chalk')

export class ChalkedConsoleLogger {

	info(...message) {
		console.log(...message)
	}

	comment(...message) {
		message[0] = chalk.blue(message[0])
		console.log(...message)
	}

	warn(...message) {
		message[0] = chalk.yellow(message[0])
		console.log(...message)
	}

	error(...message) {
		message[0] = chalk.bgRed.white(message[0])
		console.log(...message)
	}

	success(...message) {
		message[0] = chalk.green(message[0])
		console.log(...message)
	}

}
<commit_msg>Updated ChalkedConsoleLogger to use a chalk instance h/t @snlamm<commit_after>import { constructor as Chalk } from 'chalk'
const chalk = new Chalk({ enabled: true })

export class ChalkedConsoleLogger {

	info(...message) {
		console.log(...message)
	}

	comment(...message) {
		message[0] = chalk.blue(message[0])
		console.log(...message)
	}

	warn(...message) {
		message[0] = chalk.yellow(message[0])
		console.log(...message)
	}

	error(...message) {
		message[0] = chalk.bgRed.white(message[0])
		console.log(...message)
	}

	success(...message) {
		message[0] = chalk.green(message[0])
		console.log(...message)
	}

}
<|endoftext|>


<commit_before>/*~
-- KNOT EQUIVALENCE VIEWS ---------------------------------------------------------------------------------------------
--
-- Equivalence views combine the identity and equivalent parts of a knot into a single view, making
-- it look and behave like a regular knot. They also make it possible to retrieve data for only the
-- given equivalent.
--
-- @equivalent  the equivalent that you want to retrieve data for
--
~*/
var knot;
while (knot = schema.nextKnot()) {
    if(schema.EQUIVALENCE && knot.isEquivalent()) {
/*~
-- Knot equivalence view ----------------------------------------------------------------------------------------------
-- $knot.name view and parametrized view
-----------------------------------------------------------------------------------------------------------------------
IF Object_ID('$knot.capsule$.$knot.name', 'V') IS NULL
BEGIN
    EXEC('
    CREATE VIEW [$knot.capsule].[$knot.name] WITH SCHEMABINDING
    AS
    SELECT
        $(schema.METADATA)? v.$knot.metadataColumnName,
        i.$knot.identityColumnName,
        v.$knot.equivalentColumnName,
        $(knot.hasChecksum())? v.$knot.checksumColumnName,
        v.$knot.valueColumnName
    FROM
        [$knot.capsule].[$knot.identityName] i
    JOIN
        [$knot.capsule].[$knot.equivalentName] v
    ON
        v.$knot.identityColumnName = i.$knot.identityColumnName;
    ');
END
GO
IF Object_ID('$knot.capsule$.e$knot.name', 'IF') IS NULL
BEGIN
    EXEC('
    CREATE FUNCTION [$knot.capsule].[e$knot.name] (
        @equivalent $schema.metadata.equivalentRange
    )
    RETURNS TABLE WITH SCHEMABINDING AS RETURN
    SELECT
        $(schema.METADATA)? $knot.metadataColumnName,
        $knot.identityColumnName,
        $knot.equivalentColumnName,
        $(knot.hasChecksum())? $knot.checksumColumnName,
        $knot.valueColumnName
    FROM
        [$knot.capsule].[$knot.name]
    WHERE
        $knot.equivalentColumnName = @equivalent;
    ');
END
GO
~*/

    }
}<commit_msg>Translated knot equivalnece view creation code to PostgreSQL format.<commit_after>var knot;

while (knot = schema.nextKnot()) {
    if(schema.EQUIVALENCE && knot.isEquivalent()) {
/*~

-- KNOT EQUIVALENCE VIEWS ---------------------------------------------------------------------------------------------
--
-- Equivalence views combine the identity and equivalent parts of a knot into a single view, making
-- it look and behave like a regular knot. They also make it possible to retrieve data for only the
-- given equivalent.
--
-- equivalent  the equivalent that you want to retrieve data for
--
-- Knot equivalence view ----------------------------------------------------------------------------------------------
-- $knot.name view and parametrized view
-----------------------------------------------------------------------------------------------------------------------

CREATE OR REPLACE VIEW \"$knot.name\" AS
    SELECT
        $(schema.METADATA)? v.$knot.metadataColumnName,
        i.$knot.identityColumnName,
        v.$knot.equivalentColumnName,
        $(knot.hasChecksum())? v.$knot.checksumColumnName,
        v.$knot.valueColumnName
    FROM
        $knot.identityName i
    JOIN
        $knot.equivalentName v
    ON
        v.$knot.identityColumnName = i.$knot.identityColumnName;

CREATE OR REPLACE FUNCTION e$knot.name (
    equivalent $schema.metadata.equivalentRange
) RETURNS TABLE (
    $(schema.METADATA)? $knot.metadataColumnName $schema.metadata.metadataType,
    $knot.identityColumnName $knot.identity,
    $knot.equivalentColumnName $schema.metadata.equivalentRange,
    $(knot.hasChecksum())? $knot.checksumColumnName bytea,
    $knot.valueColumnName $knot.dataRange
) AS '
    SELECT
        $(schema.METADATA)? $knot.metadataColumnName,
        $knot.identityColumnName,
        $knot.equivalentColumnName,
        $(knot.hasChecksum())? $knot.checksumColumnName,
        $knot.valueColumnName
    FROM
        \"$knot.name\"
    WHERE
        $knot.equivalentColumnName = equivalent;
' LANGUAGE SQL;
~*/
    }
}<|endoftext|>


<commit_before>'use strict'

var fs = require('fs');
var parse = require('csv-parse');
var iconv = require('iconv-lite');

var aErrors = new Array();

//stop-gap solution to handling of invalid characters - now may be unnecessary due to improved file encoding handling
//left for now to help ensure that script can execute without crashing
function removeInvalidChars( inputString, inputSource, loggingString ) {
	var outputString = inputString;
	if( !loggingString ) {
			loggingString = inputString;
	}

	if( !(new RegExp(/^((\u0009|\u000A|\u000D|[\u0020-\uD7FF])|([\uD800-\uDBFF][\uDC00-\uDFFF]))*$/).test(outputString)) ) {
		outputString = outputString.replace(/[^\u0009\u000A\u000D\u0020-\uD7FF\uD800-\uDBFF\uDC00-\uDFFF]/g, "");
		aErrors.push( inputSource + ":" + loggingString + '\r\n' + "Fix:" + outputString)
	}
	if( outputString ) {
		outputString = outputString.trim();
	}
	return outputString;
}

var arrRows = new Array(); //an array to contain the top level items as returned by the processLearningItem function

//pull input and output filenames from the command line - expected format is
//USAGE:
//		node index.js INPUTFILENAME [OUTPUTFILENAME]
//
//output file will default to the input file name with a .xml file extension added to it
var inputFileName = "", outputFileNameTemplate = "", outputPlaceHolder = "~!@!~", errorFileName = "", interimFileName, outputFileName, outputFolderName;

if( process.argv.length < 3 ) {
	console.error( "ERROR: Missing command line arguments.\r\n\r\nUSAGE: \r\n node index.js INPUTFILENAME [OUTPUTOLDERNAME]\r\n\r\OUTPUTOLDERNAME is optional, if ommitted the utility will use INPUTFILENAME and append a .xml extension\r\n");
	return;
}

inputFileName = process.argv[2];
outputFolderName = inputFileName + "-output";
outputFileNameTemplate = outputFolderName + "/" + outputPlaceHolder + ".txt";

let mappingsFile = "", mapMappings = new Map();
if( process.argv.length >= 4 ) {
	mappingsFile = process.argv[3];

	let objMappings = JSON.parse( fs.readFileSync(mappingsFile) );
	for( let mapping of objMappings ) {
		for( let prefix of mapping.prefixes ) {
			mapMappings.set(prefix, mapping.group);
		}
	}
}

if( !fs.existsSync(outputFolderName) ) {
	fs.mkdirSync(outputFolderName);
}

interimFileName = outputFileNameTemplate.replace(outputPlaceHolder, "") + ".interim.csv";
errorFileName = outputFileNameTemplate.replace(outputPlaceHolder, "") + ".error.txt"

//START: Output File
var options = {declaration: {
	encoding: "UTF-8",
	version: "1.0"
}};

const HS_EDULEVEL = "9,10,11,12";

//output helpful messages for files to be used
console.log("Input file identified as: ", inputFileName);
console.log("Output filename template identified as: ", outputFileNameTemplate);

let arraySorter = (e1, e2) => {
	let depth = 0;
	while( (depth < 4) && (e1[depth] == e2[depth]) ) {
		depth++;
	}
	if( e1[depth].toUpperCase() < e2[depth].toUpperCase() ) {
		return -1;
	} else {
		return 1;
	}
}

let mapOverall = new Map();

//parse the input CSV file
//NOTE: File is expected to have a header row that should be ignored
var parser = parse( {delimiter: ','}, (err, data) => {

	if( err ) {
		console.error(err);
	}

	data.shift(); //skip over the header row in the file

	let newdata = new Array();

	//add grouping to the first column of every row
	for( let row of data ) {
		let grouping = row[0].substr(0,1);
		let found = false;
		if( isNaN(grouping) ) {
			grouping = row[0].split(":")[0]
		}
		for( let mapping of mapMappings.keys() ) {
			if( grouping.substr(0, mapping.length) == mapping ) {
				grouping = mapMappings.get(mapping);
				found = true;
				break;
			}
		}
		row.unshift(grouping);
	}

	var numRows = data.length;
	if( numRows <= 1 ) return;	//no work to do here

	var header = data[1];
	var depth = header.length;
	if( depth <=1 ) return;	//no work to do here

	var maxDepth = 0, maxDepthIndex = 0, currentDepth = 0;
	const HEADER_ROW = "Hierarchy|EducationLevel|Notation|Description";
	//arrRows.push(HEADER_ROW);
//4GM: General Music - 4,4GM.A: Skills and Techniques/Performance ,"4GM.A.1: sing, alone and with others, a varied repertoire of music",4GM.A.1.a: sing melodies expressively using appropriate head voice (accompanied and unaccompanied) demonstrating awareness of the tonal center
	//Hierarchy|EducationLevel|Notation|Description
	//|4||General Music
	//\t|4|4GM.A|Skills and Techniques/Performance
	//\t\t|4|4GM.A.1|sing, alone and with others, a varied repertoire of music
	//\t\t|4|4GM.A.1.a|sing melodies expressively using appropriate head voice (accompanied and unaccompanied) demonstrating awareness of the tonal center
	var currentFirstLevel = "", currentSecondLevel = "", currentThirdLevel = "", currentFourthLevel, currentGradeLevel = "", currentNotation = "", placeholderVal, prevPlaceholderVal = "";
	var prevFirstLevel = "", prevSecondLevel = "", prevThirdLevel = "";

	var eduLevel, notation, desc;

	//go through each row in the array of items
	for( var i = 0; i < numRows; i++ ) {
		currentDepth = data[i].length-1;
		if( currentDepth < 2) {
			continue;	//an empty row or a row with no sub-items
		}

		placeholderVal = data[i][0];
		currentFirstLevel = data[i][1];
		currentSecondLevel = data[i][2];
		currentThirdLevel = data[i][3];
		currentFourthLevel = data[i][4];

		eduLevel = currentFirstLevel.substr(0,1);
		//placeholderVal = eduLevel;
		if( isNaN(eduLevel) ) {
			eduLevel = HS_EDULEVEL;
		}

		// if( placeholderVal != prevPlaceholderVal  ) {
		// 	if( prevPlaceholderVal != "" ) {
		// 		outputFileName = outputFileNameTemplate.replace(outputPlaceHolder, prevPlaceholderVal.replace(/[\\/:*?\"<>|]/g,""));
		// 		fs.writeFileSync(outputFileName, arrRows.join("\r\n"), options);

		// 		arrRows = [];
		// 		arrRows.push(HEADER_ROW);
		// 	}

		// 	prevPlaceholderVal = placeholderVal;
		// }
		if( !mapOverall.has(placeholderVal) ) {
			mapOverall.set(placeholderVal, new Array());
			mapOverall.get(placeholderVal).push(HEADER_ROW);
		}
		if( currentFirstLevel != prevFirstLevel ) {
			notation = currentFirstLevel.split(":")[0];
			desc = removeInvalidChars(currentFirstLevel.split(":")[1], 1);

			mapOverall.get(placeholderVal).push(`|${eduLevel}|${notation}|${desc}`);

			prevFirstLevel = currentFirstLevel;
		}

		if( currentSecondLevel != prevSecondLevel ) {
			notation = currentSecondLevel.split(":")[0];
			desc = removeInvalidChars(currentSecondLevel.split(":")[1], 2);

			mapOverall.get(placeholderVal).push(`\t|${eduLevel}|${notation}|${desc}`);

			prevSecondLevel = currentSecondLevel;
		}

		if( currentThirdLevel != prevThirdLevel ) {
			notation = currentThirdLevel.split(":")[0];
			desc = removeInvalidChars(currentThirdLevel.split(":")[1],3);

			mapOverall.get(placeholderVal).push(`\t\t|${eduLevel}|${notation}|${desc}`);

			prevThirdLevel = currentThirdLevel;
		}

		notation = currentFourthLevel.split(":")[0];
		desc = removeInvalidChars(currentFourthLevel.split(":")[1],4);

		mapOverall.get(placeholderVal).push(`\t\t|${eduLevel}|${notation}|${desc}`);

	}

	// if( currentFirstLevel != "" ) {
	// 	outputFileName = outputFileNameTemplate.replace(outputPlaceHolder, placeholderVal.replace(/[\\/:*?\"<>|]/g,""));
	// 	fs.writeFileSync(outputFileName, arrRows.join("\r\n"), options);

	// 	arrRows = [];
	// }

	for( let placeholder of mapOverall.keys() ) {
		outputFileName = outputFileNameTemplate.replace(outputPlaceHolder, placeholder.replace(/[\\/:*?\"<>|]/g,""));
		fs.writeFileSync(outputFileName, mapOverall.get(placeholder).join("\r\n"), options);
	}

	var currentDate = new Date();
	if( aErrors.length > 0 ) {
		console.warn("WARNING: Invalid XML characters detected, output results to: " + errorFileName);
		fs.writeFileSync( errorFileName, "### " + currentDate + ": " + aErrors.length + " errors\r\n\r\n" + aErrors.join("\r\n\r\n") );
	} else {
		if( fs.existsSync(errorFileName) ) {
			fs.writeFileSync( errorFileName, "### " + currentDate + ": 0 errors")
		}
	}
});

//ensuring that the file encoding is one that will not cause issues
// iconv.skipDecodeWarning = true;
// var inputFileContents = fs.readFileSync(inputFileName, {encoding: "binary"});
// var outputFileContents = iconv.decode(inputFileContents, "win1251");
// fs.writeFileSync(interimFileName, outputFileContents);
// fs.createReadStream( interimFileName ).pipe( parser );

fs.createReadStream(inputFileName).pipe( parser );

//provide message to user to let them know it is still running
console.log("Processing...");

<commit_msg>fixed issue with rows not have all columns<commit_after>'use strict'

var fs = require('fs');
var parse = require('csv-parse');
var iconv = require('iconv-lite');

var aErrors = new Array();

//stop-gap solution to handling of invalid characters - now may be unnecessary due to improved file encoding handling
//left for now to help ensure that script can execute without crashing
function removeInvalidChars( inputString, inputSource, loggingString ) {
	var outputString = inputString;
	if( !loggingString ) {
			loggingString = inputString;
	}

	if( !(new RegExp(/^((\u0009|\u000A|\u000D|[\u0020-\uD7FF])|([\uD800-\uDBFF][\uDC00-\uDFFF]))*$/).test(outputString)) ) {
		outputString = outputString.replace(/[^\u0009\u000A\u000D\u0020-\uD7FF\uD800-\uDBFF\uDC00-\uDFFF]/g, "");
		aErrors.push( inputSource + ":" + loggingString + '\r\n' + "Fix:" + outputString)
	}
	if( outputString ) {
		outputString = outputString.trim();
	}
	return outputString;
}

var arrRows = new Array(); //an array to contain the top level items as returned by the processLearningItem function

//pull input and output filenames from the command line - expected format is
//USAGE:
//		node index.js INPUTFILENAME [OUTPUTFILENAME]
//
//output file will default to the input file name with a .xml file extension added to it
var inputFileName = "", outputFileNameTemplate = "", outputPlaceHolder = "~!@!~", errorFileName = "", interimFileName, outputFileName, outputFolderName;

if( process.argv.length < 3 ) {
	console.error( "ERROR: Missing command line arguments.\r\n\r\nUSAGE: \r\n node index.js INPUTFILENAME [OUTPUTOLDERNAME]\r\n\r\OUTPUTOLDERNAME is optional, if ommitted the utility will use INPUTFILENAME and append a .xml extension\r\n");
	return;
}

inputFileName = process.argv[2];
outputFolderName = inputFileName + "-output";
outputFileNameTemplate = outputFolderName + "/" + outputPlaceHolder + ".txt";

let mappingsFile = "", mapMappings = new Map();
if( process.argv.length >= 4 ) {
	mappingsFile = process.argv[3];

	let objMappings = JSON.parse( fs.readFileSync(mappingsFile) );
	for( let mapping of objMappings ) {
		for( let prefix of mapping.prefixes ) {
			mapMappings.set(prefix, mapping.group);
		}
	}
}

if( !fs.existsSync(outputFolderName) ) {
	fs.mkdirSync(outputFolderName);
}

interimFileName = outputFileNameTemplate.replace(outputPlaceHolder, "") + ".interim.csv";
errorFileName = outputFileNameTemplate.replace(outputPlaceHolder, "") + ".error.txt"

//START: Output File
var options = {declaration: {
	encoding: "UTF-8",
	version: "1.0"
}};

const HS_EDULEVEL = "9,10,11,12";

//output helpful messages for files to be used
console.log("Input file identified as: ", inputFileName);
console.log("Output filename template identified as: ", outputFileNameTemplate);

let arraySorter = (e1, e2) => {
	let depth = 0;
	while( (depth < 4) && (e1[depth] == e2[depth]) ) {
		depth++;
	}
	if( e1[depth].toUpperCase() < e2[depth].toUpperCase() ) {
		return -1;
	} else {
		return 1;
	}
}

let mapOverall = new Map();

//parse the input CSV file
//NOTE: File is expected to have a header row that should be ignored
var parser = parse( {delimiter: ','}, (err, data) => {

	if( err ) {
		console.error(err);
	}

	data.shift(); //skip over the header row in the file

	let newdata = new Array();

	//add grouping to the first column of every row
	for( let row of data ) {
		let grouping = row[0].substr(0,1);
		let found = false;
		if( isNaN(grouping) ) {
			grouping = row[0].split(":")[0]
		}
		for( let mapping of mapMappings.keys() ) {
			if( grouping.substr(0, mapping.length) == mapping ) {
				grouping = mapMappings.get(mapping);
				found = true;
				break;
			}
		}
		row.unshift(grouping);
	}

	var numRows = data.length;
	if( numRows <= 1 ) return;	//no work to do here

	var header = data[1];
	var depth = header.length;
	if( depth <=1 ) return;	//no work to do here

	var maxDepth = 0, maxDepthIndex = 0, currentDepth = 0;
	const HEADER_ROW = "Hierarchy|EducationLevel|Notation|Description";
	//arrRows.push(HEADER_ROW);
//4GM: General Music - 4,4GM.A: Skills and Techniques/Performance ,"4GM.A.1: sing, alone and with others, a varied repertoire of music",4GM.A.1.a: sing melodies expressively using appropriate head voice (accompanied and unaccompanied) demonstrating awareness of the tonal center
	//Hierarchy|EducationLevel|Notation|Description
	//|4||General Music
	//\t|4|4GM.A|Skills and Techniques/Performance
	//\t\t|4|4GM.A.1|sing, alone and with others, a varied repertoire of music
	//\t\t|4|4GM.A.1.a|sing melodies expressively using appropriate head voice (accompanied and unaccompanied) demonstrating awareness of the tonal center
	var currentFirstLevel = "", currentSecondLevel = "", currentThirdLevel = "", currentFourthLevel, currentGradeLevel = "", currentNotation = "", placeholderVal, prevPlaceholderVal = "";
	var prevFirstLevel = "", prevSecondLevel = "", prevThirdLevel = "";

	var eduLevel, notation, desc;

	//go through each row in the array of items
	for( var i = 0; i < numRows; i++ ) {
		currentDepth = data[i].length-1;
		if( currentDepth < 2) {
			continue;	//an empty row or a row with no sub-items
		}

		placeholderVal = data[i][0];
		currentFirstLevel = data[i][1];
		currentSecondLevel = data[i][2];
		currentThirdLevel = data[i][3];
		currentFourthLevel = data[i][4];

		eduLevel = currentFirstLevel.substr(0,1);
		//placeholderVal = eduLevel;
		if( isNaN(eduLevel) ) {
			eduLevel = HS_EDULEVEL;
		}

		// if( placeholderVal != prevPlaceholderVal  ) {
		// 	if( prevPlaceholderVal != "" ) {
		// 		outputFileName = outputFileNameTemplate.replace(outputPlaceHolder, prevPlaceholderVal.replace(/[\\/:*?\"<>|]/g,""));
		// 		fs.writeFileSync(outputFileName, arrRows.join("\r\n"), options);

		// 		arrRows = [];
		// 		arrRows.push(HEADER_ROW);
		// 	}

		// 	prevPlaceholderVal = placeholderVal;
		// }
		if( !mapOverall.has(placeholderVal) ) {
			mapOverall.set(placeholderVal, new Array());
			mapOverall.get(placeholderVal).push(HEADER_ROW);
		}
		if( currentFirstLevel != prevFirstLevel ) {
			notation = currentFirstLevel.split(":")[0];
			desc = removeInvalidChars(currentFirstLevel.split(":")[1], 1);

			mapOverall.get(placeholderVal).push(`|${eduLevel}|${notation}|${desc}`);

			prevFirstLevel = currentFirstLevel;
		}

		if( currentSecondLevel != prevSecondLevel ) {
			notation = currentSecondLevel.split(":")[0];
			desc = removeInvalidChars(currentSecondLevel.split(":")[1], 2);

			mapOverall.get(placeholderVal).push(`\t|${eduLevel}|${notation}|${desc}`);

			prevSecondLevel = currentSecondLevel;
		}

		if( currentThirdLevel != prevThirdLevel ) {
			notation = currentThirdLevel.split(":")[0];
			desc = removeInvalidChars(currentThirdLevel.split(":")[1],3);

			mapOverall.get(placeholderVal).push(`\t\t|${eduLevel}|${notation}|${desc}`);

			prevThirdLevel = currentThirdLevel;
		}

		notation = currentFourthLevel.split(":")[0];
		desc = removeInvalidChars(currentFourthLevel.split(":")[1],4);

		if( notation && desc ) {
			mapOverall.get(placeholderVal).push(`\t\t|${eduLevel}|${notation}|${desc}`);
		}

	}

	// if( currentFirstLevel != "" ) {
	// 	outputFileName = outputFileNameTemplate.replace(outputPlaceHolder, placeholderVal.replace(/[\\/:*?\"<>|]/g,""));
	// 	fs.writeFileSync(outputFileName, arrRows.join("\r\n"), options);

	// 	arrRows = [];
	// }

	for( let placeholder of mapOverall.keys() ) {
		outputFileName = outputFileNameTemplate.replace(outputPlaceHolder, placeholder.replace(/[\\/:*?\"<>|]/g,""));
		fs.writeFileSync(outputFileName, mapOverall.get(placeholder).join("\r\n"), options);
	}

	var currentDate = new Date();
	if( aErrors.length > 0 ) {
		console.warn("WARNING: Invalid XML characters detected, output results to: " + errorFileName);
		fs.writeFileSync( errorFileName, "### " + currentDate + ": " + aErrors.length + " errors\r\n\r\n" + aErrors.join("\r\n\r\n") );
	} else {
		if( fs.existsSync(errorFileName) ) {
			fs.writeFileSync( errorFileName, "### " + currentDate + ": 0 errors")
		}
	}
});

//ensuring that the file encoding is one that will not cause issues
// iconv.skipDecodeWarning = true;
// var inputFileContents = fs.readFileSync(inputFileName, {encoding: "binary"});
// var outputFileContents = iconv.decode(inputFileContents, "win1251");
// fs.writeFileSync(interimFileName, outputFileContents);
// fs.createReadStream( interimFileName ).pipe( parser );

fs.createReadStream(inputFileName).pipe( parser );

//provide message to user to let them know it is still running
console.log("Processing...");

<|endoftext|>


<commit_before>/*
 SeaThree, Realtime Twitter Translations
 Copyright (C) 2014 Nathaniel Smith and Benjamin Valentine

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
(function (ng) {
  var List,
      User,
      refresh,
      listsToUsers,
      refreshInterval = 30000,
      // TODO obviously this cannot be hardcoded.
      seathreeUrl = 'http://localhost:8888/tweets-for-many';

  List = function (name, users) {
    this.name = name;
    this.users = users;
    this.selected = false;
  };

  User = function (username, src, tgt) {
    this.username = username;
    this.src = src || 'es';
    this.tgt = tgt || 'tgt';
    this.tweets = [];
  };

  listsToUsers = function (lists) {
    return lists.map(function (list) {return list.users;}).
      reduce(function (userList0, userList1) {
             return userList0.concat(userList1);
           }).
      sort(function (user0, user1) {
             if (user0.username < user1.username)
               return -1;
             if (user0.username > user1.username)
               return 1;
             return 0;
           }).
      reduce(function (list, user) {
             if (list.length == 0)
               list.push(user);
             if (list[list.length-1].username != user.username)
               list.push(user);
             return list;
           }, []);
  };

  refresh = function ($http, lists) {
    var userList = listsToUsers(lists);
    $http.get(seathree_url + '?data=' + JSON.stringify(userList)).success(function (data) {
      // TODO need to distribute all of the user tweets into the various lists.
    });
  };

  ng.module('SeaThree', []).

  controller('TweetsCtrl', function ($scope, $http, $interval) {
    var lists = [
      new List('Mexico', [
        new User('GobiernoDF')
      ]),
      new List('United States', [
        new User('nate_smith', 'en', 'es')
      ]),
      new List('Organizations', []),
      new List('My List', [])
    ];
    // TODO keep "All" updated as My List changes.
    lists.unshift(new List('All', listsToUsers(lists)));

    $scope.lists = lists;

    $scope.toggleListAt = function (index) {
      lists[index].selected = !lists[index].selected;
    };

    $scope.isSelected = function (list) {
      return list.selected == true;
    };
    $interval(function () {
      refresh($http, lists.filter($scope.isSelected);

    }, refreshInterval);

    $interval(refresh.bind(null, $http, lists), 30000);

    // TODO restore selected lists from localStorage
    // TODO setup polling interval
  }).

  controller('LanguageCtrl', function ($scope) {
    // TODO. Putting this off until I learn more about
    // internationalization.
  });

})(angular);
<commit_msg>Cleanup angular code. Still need to run/test/complete.<commit_after>(function (ng, _) {
  var SEATHREEURL   = 'http://localhost:8888/tweets-for-many',
      FETCHINTERVAL = 5000;

  ng.module('SeaThree', [])
  .controller('TweetsCtrl', function ($scope, $http, $interval) {
    var findUser,
        List,
        fetch;
    List = function (name, usernames) {
      this.name = name;
      this.usernames = usernames;
      this.selected = false;
      this.tweets = [];
    };

    $scope.lists = [
      new List('Mexico', ['GobiernoDF']),
      new List('United States', ['nate_smith']),
      new List('Organizations', []),
      new List('My List', [])
    ];
    $scope.lists.unshift(new List('All', _.chain($scope.lists)
                                         .pluck('usernames')
                                         .flatten()
                                         .unique()
                                         .value()));

    $scope.users = [{
      username: 'GobiernoDF',
      src: 'es',
      tgt: 'en',
      tweets: []
    }, {
      username: 'nate_smith',
      src:'en',
      tgt:'es',
      twwets: []
    }];

    findUser = function (users, username) {
      return _(users).find(function (user) {
               return user.username === username;
             });
    };

    $scope.isSelected = function (list) {return list.selected;};
    $scope.toggleListAt = function (index) {
      $scope.lists[index].selected = !$scope.lists[index].selected;
    };

    fetch = function () {
      var data = _($scope.users).map(function (user) {
                   return _(user).pick('username', 'src', 'tgt');
                 });
      $http.get(SEATHREEURL + '?data=' + JSON.stringify(data)).success(function (users) {
        $scope.users = users;
      });
    };

    $scope.$watch('users', function () {
      // When users is updated, we must update the lists.
      _($scope.lists).each(function (list) {
        var tweets = _(list.usernames).map(function (username) {
          return findUser($scope.users, username).tweets;
        });
        list.tweets = _(tweets).flatten();
      });
    });

    // Start polling.
    $interval(fetch, FETCHINTERVAL);
  })
  .controller('LanguageCtrl', function ($scope) {
    // TODO
  });

})(angular, _);
<|endoftext|>


<commit_before>var PeopleList = angular.module('PeopleList', []);

function mainController($scope, $http) {
	$scope.formData = {};

	// when landing on the page
	$http.get('/api/getList')
		.success(function(data) {
			$scope.students = data;
		})
		.error(function(data) {
			console.log('Error: ' + data);
		});

	var reloadData=$scope.reloadData = function()
	{
		$http.get('/api/getList')
			.success(function(data) {
				$scope.students = data;
			})
			.error(function(data) {
					console.log('Error: ' + data);
			});
	}

	$scope.lock = {};
	$scope.come = {};
	$scope.turnGreen = function (){
			$scope.come.style = {"color":"green"};
	    $scope.lock.style = {"color":"green"};
	}

	$scope.turnRed = function() {
			$scope.come.style = {"color":"red"};
	    $scope.lock.style = {"color":"red"};
	}

	$scope.lockColor = function(lock){
		if(lock){
			$scope.turnRed();
			return "鎖定";
		}
		else{
			$scope.turnGreen();
			return "未鎖定";
		}
	}

	$scope.comeColor = function(come){
		if(!come){
		  $scope.turnRed();
			return "沒到";
		}
		else{
			$scope.turnGreen();
			return "有到";
		}
	}

	$scope.changeStudent = function(stu_id) {
		var post = {  "stu_id":stu_id };
		$http.post('/api/changeStudent/' , JSON.stringify(post))
			.success(function(data) {
				reloadData();
			})
			.error(function(data) {
				console.log('Error: ' + data);
				reloadData();
			});
	};

	$scope.lockStudent = function(stu_id) {
		var post = {  "stu_id":stu_id };
		$http.post('/api/lockStudent/' , JSON.stringify(post))
			.success(function(data) {
				reloadData();
			})
			.error(function(data) {
				console.log('Error: ' + data);
				reloadData();
			});
	};

	$scope.deleteStudent = function(stu_id) {
		var post = {  "stu_id":stu_id };
		$http.post('/api/deleteStudent/' , JSON.stringify(post))
			.success(function(data) {
				reloadData();
			})
			.error(function(data) {
				console.log('Error: ' + data);
				reloadData();
			});
	};

	var socket = io.connect('http://peterlee0127.no-ip.org:8080/');
	// var socket = io.connect('your server ip:port');
	// example var socket = io.connect('192.168.1.1:8080');

		socket.on('connect', function(data) {

		});

		socket.on('disconnect', function(data) {

		});

		socket.on('reloadData', function(data){
			reloadData();
		});
}
<commit_msg>update reloadData to 		$scope.reloadData<commit_after>var PeopleList = angular.module('PeopleList', []);

function mainController($scope, $http) {
	$scope.formData = {};

	// when landing on the page
	$http.get('/api/getList')
		.success(function(data) {
			$scope.students = data;
		})
		.error(function(data) {
			console.log('Error: ' + data);
		});

	$scope.reloadData = function()
	{
		$http.get('/api/getList')
			.success(function(data) {
				$scope.students = data;
			})
			.error(function(data) {
					console.log('Error: ' + data);
			});
	}

	$scope.lock = {};
	$scope.come = {};
	$scope.turnGreen = function (){
			$scope.come.style = {"color":"green"};
	    $scope.lock.style = {"color":"green"};
	}

	$scope.turnRed = function() {
			$scope.come.style = {"color":"red"};
	    $scope.lock.style = {"color":"red"};
	}

	$scope.lockColor = function(lock){
		if(lock){
			$scope.turnRed();
			return "鎖定";
		}
		else{
			$scope.turnGreen();
			return "未鎖定";
		}
	}

	$scope.comeColor = function(come){
		if(!come){
		  $scope.turnRed();
			return "沒到";
		}
		else{
			$scope.turnGreen();
			return "有到";
		}
	}

	$scope.changeStudent = function(stu_id) {
		var post = {  "stu_id":stu_id };
		$http.post('/api/changeStudent/' , JSON.stringify(post))
			.success(function(data) {
				$scope.reloadData();
			})
			.error(function(data) {
				console.log('Error: ' + data);
				$scope.reloadData();
			});
	};

	$scope.lockStudent = function(stu_id) {
		var post = {  "stu_id":stu_id };
		$http.post('/api/lockStudent/' , JSON.stringify(post))
			.success(function(data) {
					$scope.reloadData();
			})
			.error(function(data) {
				console.log('Error: ' + data);
					$scope.reloadData();
			});
	};

	$scope.deleteStudent = function(stu_id) {
		var post = {  "stu_id":stu_id };
		$http.post('/api/deleteStudent/' , JSON.stringify(post))
			.success(function(data) {
				$scope.reloadData();
			})
			.error(function(data) {
				console.log('Error: ' + data);
				$scope.reloadData();
			});
	};

	var socket = io.connect('http://peterlee0127.no-ip.org:8080/');
	// var socket = io.connect('your server ip:port');
	// example var socket = io.connect('192.168.1.1:8080');

		socket.on('connect', function(data) {

		});

		socket.on('disconnect', function(data) {

		});

		socket.on('reloadData', function(data){
				$scope.reloadData();
		});
}
<|endoftext|>