<commit_before>// graphite.js

function build_url(options) {
    var url = options.url + "?";

    // use random parameter to force image refresh
    options["_t"] = options["_t"] || Math.random();

    $.each(options, function (key, value) {
        if (key === "target") { // png
            $.each(value, function (index, value) {
                url += "&target=" + value;
            });
        } else if (key === "targets") { // rickshaw
            $.each(value, function (index, value) {
                    url += "&target=" + value.target;
            });
        } else if (value !== null && key !== "url") {
            url += "&" + key + "=" + value;
        }
    });

    url = url.replace(/\?&/, "?");
    return url;
};

function find_definition (target_graphite, options) {
    var matching_i = undefined;
    for (var cfg_i = 0; cfg_i < options.targets.length && matching_i == undefined; cfg_i++) {
        // alias in config
        // currently this is not needed because we don't actually send aliases to graphite (yet)
        if(options.targets[cfg_i].name != undefined && options.targets[cfg_i].name == target_graphite.target) {
            matching_i = cfg_i;
        }
        // string match (no globbing)
        else if(options.targets[cfg_i].target == target_graphite.target) {
            matching_i = cfg_i;
        }
        // glob match?
        else if(target_graphite.target.graphiteGlob(options.targets[cfg_i].target)) {
            matching_i = cfg_i;
        }
    }
    if (matching_i == undefined) {
        console.error ("internal error: could not figure out which target_option target_graphite '" +
                target_graphite.target + "' comes from");
        return [];
    }
    return options.targets[matching_i];
}

(function ($) {
    $.fn.graphite = function (options) {
        if (options === "update") {
            $.fn.graphite.update(this, arguments[1]);
            return this;
        }

        // Initialize plugin //
        options = options || {};
        var settings = $.extend({}, $.fn.graphite.defaults, options);

        return this.each(function () {
            $this = $(this);

            $this.data("graphOptions", settings);
            $.fn.graphite.render($this, settings);
        });

    };

    $.fn.graphite.render = function($img, options) {
        $img.attr("src", build_url(options));
        $img.attr("height", options.height);
        $img.attr("width", options.width);
    };

    $.fn.graphite.update = function($img, options) {
        options = options || {};
        $img.each(function () {
            $this = $(this);
            var settings = $.extend({}, $this.data("graphOptions"), options);
            $this.data("graphOptions", settings);
            $.fn.graphite.render($this, settings);
        });
    };

    // note: graphite json output is a list of dicts like:
    // {"datapoints": [...], "target": "<metricname>" }
    // if you did alias(series, "foo") then "target" will contain the alias
    // (loosing the metricname which is bad, esp. when you had a glob with an alias, then you don't know what's what)
    // rickshaw: options.series is a list of dicts like:
    // { name: "alias", color: "foo", data: [{x: (...), y: (...)} , ...]}
    // we basically tell users to use this dict, with extra 'target' to specify graphite target string
    // flot: d = [[<ts>, <val>], (...)]
    // plot ($(..), [d], ..)
    $.fn.graphiteRick = function (options, on_error) {
        options = options || {};
        var settings = $.extend({}, $.fn.graphite.defaults, options);

        return this.each(function () {
            $this = $(this);
            $this.data("graphOptions", settings);
            $.fn.graphiteRick.render(this, settings, on_error);
        });
    };

    $.fn.graphiteFlot = function (options, on_error) {
        options = options || {};
        var settings = $.extend({}, $.fn.graphite.defaults, options);

        return this.each(function () {
            $this = $(this);
            $this.data("graphOptions", settings);
            $.fn.graphiteFlot.render(this, settings, on_error);
        });
    };

    $.fn.graphiteFlot.render = function(div, options, on_error) {
        $div = $(div);
        $div.height(options.height);
        $div.width(options.width);
        var drawFlot = function(response) {
            var all_targets = [];
            if(response.length == 0 ) {
                console.warn("no data in response");
            }
            for (var res_i = 0; res_i < response.length; res_i++) {
                var target = find_definition(response[res_i], options);
                target.label = target.name // flot wants 'label'
                target.data = [];
                for (var i in response[res_i].datapoints) {
                    target.data[i] = [response[res_i].datapoints[i][1] * 1000, response[res_i].datapoints[i][0] || 0 ];
                }
                all_targets.push(target);
            }
            // default config state modifiers (you can override them in your config objects)
            var states = {
                'stacked': {
                    'series': {'stack': true, 'lines': {'show': true, 'lineWidth': 0, 'fill': true }},
                },
                'lines': {
                    // flot lib wants 0 or null. not false o_O
                    'series': {'stack': null, 'lines': { 'show': true, 'lineWidth': 0.6, 'fill': false }}
                }
            };
            if(! 'states' in options) {
                options['states'] = {};
            }
            options['states'] = $.extend(options['states'], states);

            var buildFlotOptions = function(options) {
                if('title' in options) {
                    options['xaxes'] = [{axisLabel: options['title']}];
                }
                if('vtitle' in options) {
                    options['yaxes'] = [{position: 'left', axisLabel: options['vtitle']}];
                }
                state = options['state'] || 'lines';
                return $.extend(options, options['states'][state]);
            }
            $.plot(div, all_targets, buildFlotOptions(options));
            if (options['line_stack_toggle']) {
                var form = document.getElementById(options['line_stack_toggle']);
                if(options['state'] == 'stacked') {
                    lines_checked = '';
                    stacked_checked = ' checked';
                } else {
                    lines_checked = ' checked';
                    stacked_checked = '';
                }
                form.innerHTML= '<input type="radio" name="offset" id="lines" value="lines"'+ lines_checked +'>' +
                    'lines' +
                    '
<input type="radio" name="offset" id="stacked" value="stacked"' + stacked_checked + '>' +
                    'stack';

                form.addEventListener('change', function(e) {
                    var mode = e.target.value;
                    options['state'] = mode;
                    $.plot(div, all_targets, buildFlotOptions(options));
                }, false);
            }
        }
        $.ajax({
            accepts: {text: 'application/json'},
            cache: false,
            dataType: 'jsonp',
            jsonp: 'jsonp',
            url: build_url(options) + '&format=json',
            error: function(xhr, textStatus, errorThrown) { on_error(textStatus + ": " + errorThrown); }
        }).done(drawFlot);
    };

    $.fn.graphiteRick.render = function(div, options, on_error) {
        $div = $(div);
        $div.attr("height", options.height);
        $div.attr("width", options.width);
        var drawRick = function(response) {
            // note that response.length can be != options.targets.length.  let's call:
            // * target_graphite a targetstring as returned by graphite
            // * target_option a targetstring configuration
            // if a target_option contains * graphite will return all matches separately unless you use something to aggregate like sumSeries()
            // we must render all target_graphite's, but we must merge in the config from the corresponding target_option.
            // example: for a target_graphite 'stats.foo.bar' we must find a target_option 'stats.foo.bar' *or*
            // anything that causes graphite to match it, such as 'stats.*.bar' (this would be a bit cleaner if graphite's json
            // would include also the originally specified target string)
            // note that this code assumes each target_graphite can only be originating from one target_option,
            // in some unlikely cases this is not correct (there might be overlap between different target_options with globs)
            // but in that case I don't see why taking the settings of any of the possible originating target_options wouldn't be fine.
            var all_targets = [];
            if(response.length == 0 ) {
                console.warn("no data in response");
            }
            for (var res_i = 0; res_i < response.length; res_i++) {
                var target = find_definition(response[res_i], options);
                target.data = [];
                for (var i in response[res_i].datapoints) {
                    target.data[i] = { x: response[res_i].datapoints[i][1], y: response[res_i].datapoints[i][0] || 0 };
                }
                all_targets.push(target);
            }
            options['element'] = div;
            options['series'] = all_targets
            var graph = new Rickshaw.Graph(options);
            if(options['x_axis']) {
                var x_axis = new Rickshaw.Graph.Axis.Time( { graph: graph } );
            }
            if(options['y_axis']) {
                var y_axis = new Rickshaw.Graph.Axis.Y( {
                    graph: graph,
                    orientation: 'left',
                    tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
                    element: document.getElementById(options['y_axis']),
                });
            }
            if(options['hoover_details']) {
                var hoverDetail = new Rickshaw.Graph.HoverDetail( {
                    graph: graph
                } );
            }
            graph.render();
            if (options['legend']) {
                var legend = new Rickshaw.Graph.Legend({
                    graph: graph,
                    element: document.getElementById(options['legend'])
                });
                if(options['legend_toggle']) {
                    var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
                        graph: graph,
                        legend: legend
                    });
                }
                if(options['legend_reorder']) {
                    var order = new Rickshaw.Graph.Behavior.Series.Order({
                        graph: graph,
                        legend: legend
                    });
                }
                if(options['legend_highlight']) {
                    var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
                    graph: graph,
                    legend: legend
                    });
                }
            }
            if (options['line_stack_toggle']) {
                var form = document.getElementById(options['line_stack_toggle']);
                if(!options['renderer'] || options['renderer'] == 'area') {
                    lines_checked = '';
                    stack_checked = ' checked';
                } else {
                    lines_checked = ' checked';
                    stack_checked = '';
                }
                form.innerHTML= '<input type="radio" name="offset" id="lines" value="lines"'+ lines_checked +'>' +
                    'lines' +
                    '
<input type="radio" name="offset" id="stack" value="zero"' + stack_checked + '>' +
                    'stack';

                form.addEventListener('change', function(e) {
                    var offsetMode = e.target.value;

                    if (offsetMode == 'lines') {
                        graph.setRenderer('line');
                        graph.offset = 'zero';
                    } else {
                        graph.setRenderer('stack');
                        graph.offset = offsetMode;
                    }
                    graph.render();
                }, false);
            }
        }
        $.ajax({
            accepts: {text: 'application/json'},
            cache: false,
            dataType: 'jsonp',
            jsonp: 'jsonp',
            url: build_url(options) + '&format=json',
            error: function(xhr, textStatus, errorThrown) { on_error(textStatus + ": " + errorThrown); }
          }).done(drawRick);
    };

    // Default settings.
    // Override with the options argument for per-case setup
    // or set $.fn.graphite.defaults.<value> for global changes
    $.fn.graphite.defaults = {
        from: "-1hour",
        height: "300",
        until: "now",
        url: "/render/",
        width: "940"
    };

}(jQuery));
<commit_msg>bugfix: make fill fully opaque (wtf flot)<commit_after>// graphite.js

function build_url(options) {
    var url = options.url + "?";

    // use random parameter to force image refresh
    options["_t"] = options["_t"] || Math.random();

    $.each(options, function (key, value) {
        if (key === "target") { // png
            $.each(value, function (index, value) {
                url += "&target=" + value;
            });
        } else if (key === "targets") { // rickshaw
            $.each(value, function (index, value) {
                    url += "&target=" + value.target;
            });
        } else if (value !== null && key !== "url") {
            url += "&" + key + "=" + value;
        }
    });

    url = url.replace(/\?&/, "?");
    return url;
};

function find_definition (target_graphite, options) {
    var matching_i = undefined;
    for (var cfg_i = 0; cfg_i < options.targets.length && matching_i == undefined; cfg_i++) {
        // alias in config
        // currently this is not needed because we don't actually send aliases to graphite (yet)
        if(options.targets[cfg_i].name != undefined && options.targets[cfg_i].name == target_graphite.target) {
            matching_i = cfg_i;
        }
        // string match (no globbing)
        else if(options.targets[cfg_i].target == target_graphite.target) {
            matching_i = cfg_i;
        }
        // glob match?
        else if(target_graphite.target.graphiteGlob(options.targets[cfg_i].target)) {
            matching_i = cfg_i;
        }
    }
    if (matching_i == undefined) {
        console.error ("internal error: could not figure out which target_option target_graphite '" +
                target_graphite.target + "' comes from");
        return [];
    }
    return options.targets[matching_i];
}

(function ($) {
    $.fn.graphite = function (options) {
        if (options === "update") {
            $.fn.graphite.update(this, arguments[1]);
            return this;
        }

        // Initialize plugin //
        options = options || {};
        var settings = $.extend({}, $.fn.graphite.defaults, options);

        return this.each(function () {
            $this = $(this);

            $this.data("graphOptions", settings);
            $.fn.graphite.render($this, settings);
        });

    };

    $.fn.graphite.render = function($img, options) {
        $img.attr("src", build_url(options));
        $img.attr("height", options.height);
        $img.attr("width", options.width);
    };

    $.fn.graphite.update = function($img, options) {
        options = options || {};
        $img.each(function () {
            $this = $(this);
            var settings = $.extend({}, $this.data("graphOptions"), options);
            $this.data("graphOptions", settings);
            $.fn.graphite.render($this, settings);
        });
    };

    // note: graphite json output is a list of dicts like:
    // {"datapoints": [...], "target": "<metricname>" }
    // if you did alias(series, "foo") then "target" will contain the alias
    // (loosing the metricname which is bad, esp. when you had a glob with an alias, then you don't know what's what)
    // rickshaw: options.series is a list of dicts like:
    // { name: "alias", color: "foo", data: [{x: (...), y: (...)} , ...]}
    // we basically tell users to use this dict, with extra 'target' to specify graphite target string
    // flot: d = [[<ts>, <val>], (...)]
    // plot ($(..), [d], ..)
    $.fn.graphiteRick = function (options, on_error) {
        options = options || {};
        var settings = $.extend({}, $.fn.graphite.defaults, options);

        return this.each(function () {
            $this = $(this);
            $this.data("graphOptions", settings);
            $.fn.graphiteRick.render(this, settings, on_error);
        });
    };

    $.fn.graphiteFlot = function (options, on_error) {
        options = options || {};
        var settings = $.extend({}, $.fn.graphite.defaults, options);

        return this.each(function () {
            $this = $(this);
            $this.data("graphOptions", settings);
            $.fn.graphiteFlot.render(this, settings, on_error);
        });
    };

    $.fn.graphiteFlot.render = function(div, options, on_error) {
        $div = $(div);
        $div.height(options.height);
        $div.width(options.width);
        var drawFlot = function(response) {
            var all_targets = [];
            if(response.length == 0 ) {
                console.warn("no data in response");
            }
            for (var res_i = 0; res_i < response.length; res_i++) {
                var target = find_definition(response[res_i], options);
                target.label = target.name // flot wants 'label'
                target.data = [];
                for (var i in response[res_i].datapoints) {
                    target.data[i] = [response[res_i].datapoints[i][1] * 1000, response[res_i].datapoints[i][0] || 0 ];
                }
                all_targets.push(target);
            }
            // default config state modifiers (you can override them in your config objects)
            var states = {
                'stacked': {
                    'series': {'stack': true, 'lines': {'show': true, 'lineWidth': 0, 'fill': 1}},
                },
                'lines': {
                    // flot lib wants 0 or null. not false o_O
                    'series': {'stack': null, 'lines': { 'show': true, 'lineWidth': 0.6, 'fill': false }}
                }
            };
            if(! 'states' in options) {
                options['states'] = {};
            }
            options['states'] = $.extend(options['states'], states);

            var buildFlotOptions = function(options) {
                if('title' in options) {
                    options['xaxes'] = [{axisLabel: options['title']}];
                }
                if('vtitle' in options) {
                    options['yaxes'] = [{position: 'left', axisLabel: options['vtitle']}];
                }
                state = options['state'] || 'lines';
                return $.extend(options, options['states'][state]);
            }
            $.plot(div, all_targets, buildFlotOptions(options));
            if (options['line_stack_toggle']) {
                var form = document.getElementById(options['line_stack_toggle']);
                if(options['state'] == 'stacked') {
                    lines_checked = '';
                    stacked_checked = ' checked';
                } else {
                    lines_checked = ' checked';
                    stacked_checked = '';
                }
                form.innerHTML= '<input type="radio" name="offset" id="lines" value="lines"'+ lines_checked +'>' +
                    'lines' +
                    '
<input type="radio" name="offset" id="stacked" value="stacked"' + stacked_checked + '>' +
                    'stack';

                form.addEventListener('change', function(e) {
                    var mode = e.target.value;
                    options['state'] = mode;
                    $.plot(div, all_targets, buildFlotOptions(options));
                }, false);
            }
        }
        $.ajax({
            accepts: {text: 'application/json'},
            cache: false,
            dataType: 'jsonp',
            jsonp: 'jsonp',
            url: build_url(options) + '&format=json',
            error: function(xhr, textStatus, errorThrown) { on_error(textStatus + ": " + errorThrown); }
        }).done(drawFlot);
    };

    $.fn.graphiteRick.render = function(div, options, on_error) {
        $div = $(div);
        $div.attr("height", options.height);
        $div.attr("width", options.width);
        var drawRick = function(response) {
            // note that response.length can be != options.targets.length.  let's call:
            // * target_graphite a targetstring as returned by graphite
            // * target_option a targetstring configuration
            // if a target_option contains * graphite will return all matches separately unless you use something to aggregate like sumSeries()
            // we must render all target_graphite's, but we must merge in the config from the corresponding target_option.
            // example: for a target_graphite 'stats.foo.bar' we must find a target_option 'stats.foo.bar' *or*
            // anything that causes graphite to match it, such as 'stats.*.bar' (this would be a bit cleaner if graphite's json
            // would include also the originally specified target string)
            // note that this code assumes each target_graphite can only be originating from one target_option,
            // in some unlikely cases this is not correct (there might be overlap between different target_options with globs)
            // but in that case I don't see why taking the settings of any of the possible originating target_options wouldn't be fine.
            var all_targets = [];
            if(response.length == 0 ) {
                console.warn("no data in response");
            }
            for (var res_i = 0; res_i < response.length; res_i++) {
                var target = find_definition(response[res_i], options);
                target.data = [];
                for (var i in response[res_i].datapoints) {
                    target.data[i] = { x: response[res_i].datapoints[i][1], y: response[res_i].datapoints[i][0] || 0 };
                }
                all_targets.push(target);
            }
            options['element'] = div;
            options['series'] = all_targets
            var graph = new Rickshaw.Graph(options);
            if(options['x_axis']) {
                var x_axis = new Rickshaw.Graph.Axis.Time( { graph: graph } );
            }
            if(options['y_axis']) {
                var y_axis = new Rickshaw.Graph.Axis.Y( {
                    graph: graph,
                    orientation: 'left',
                    tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
                    element: document.getElementById(options['y_axis']),
                });
            }
            if(options['hoover_details']) {
                var hoverDetail = new Rickshaw.Graph.HoverDetail( {
                    graph: graph
                } );
            }
            graph.render();
            if (options['legend']) {
                var legend = new Rickshaw.Graph.Legend({
                    graph: graph,
                    element: document.getElementById(options['legend'])
                });
                if(options['legend_toggle']) {
                    var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
                        graph: graph,
                        legend: legend
                    });
                }
                if(options['legend_reorder']) {
                    var order = new Rickshaw.Graph.Behavior.Series.Order({
                        graph: graph,
                        legend: legend
                    });
                }
                if(options['legend_highlight']) {
                    var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
                    graph: graph,
                    legend: legend
                    });
                }
            }
            if (options['line_stack_toggle']) {
                var form = document.getElementById(options['line_stack_toggle']);
                if(!options['renderer'] || options['renderer'] == 'area') {
                    lines_checked = '';
                    stack_checked = ' checked';
                } else {
                    lines_checked = ' checked';
                    stack_checked = '';
                }
                form.innerHTML= '<input type="radio" name="offset" id="lines" value="lines"'+ lines_checked +'>' +
                    'lines' +
                    '
<input type="radio" name="offset" id="stack" value="zero"' + stack_checked + '>' +
                    'stack';

                form.addEventListener('change', function(e) {
                    var offsetMode = e.target.value;

                    if (offsetMode == 'lines') {
                        graph.setRenderer('line');
                        graph.offset = 'zero';
                    } else {
                        graph.setRenderer('stack');
                        graph.offset = offsetMode;
                    }
                    graph.render();
                }, false);
            }
        }
        $.ajax({
            accepts: {text: 'application/json'},
            cache: false,
            dataType: 'jsonp',
            jsonp: 'jsonp',
            url: build_url(options) + '&format=json',
            error: function(xhr, textStatus, errorThrown) { on_error(textStatus + ": " + errorThrown); }
          }).done(drawRick);
    };

    // Default settings.
    // Override with the options argument for per-case setup
    // or set $.fn.graphite.defaults.<value> for global changes
    $.fn.graphite.defaults = {
        from: "-1hour",
        height: "300",
        until: "now",
        url: "/render/",
        width: "940"
    };

}(jQuery));
<|endoftext|>


<commit_before>function NewStoryAdder() {
  $('a#contextual_new_story').click( function() {
    new Request({
      url: this.href,
      beforeClose: function() {
        // the following attempts to recognise a story/show url
        var url_parts = this.url.split('/');
        var last_part = url_parts[url_parts.length-1];
        var rejected = $.inArray(last_part, ['stories', 'new']);
        var not_rejected = rejected == -1;

        if (not_rejected) {
          $.ajax({
            url: this.url + '/estimate',
            success: function(html, status) {
              // add the story to the available list
              $('#stories_available>ol').prepend(html)

              // re-initialise the page
              StorySwapper.init_stories();
              $('a.move').remove();
              StorySwapper.convert_checkboxes();
              StorySwapper.show_hide_estimate_headings();

              $('a.expand').remove();
              StoryToggler.init();
            }
          });
        }
      }
    });
    return false;
  });
}

var StorySwapper = {
  init: function() {
    // create an iteration stories div
    $('#stories_available')
      .before('

Story Points (0)
Iteration stories

');

    // wrap the available div
    var available_div = $('#stories_available').remove();
    $('#stories_iteration_container').after('

Story Points (0)'+available_div.html()+'

');

    StorySwapper.init_stories();
    StorySwapper.convert_checkboxes();
    StorySwapper.bind_estimates();
    StorySwapper.update_estimates();
  },

  // add the story to the specified ol, maintaining the original order
  append_story: function(story, ol) {
    var stories = ol.find('li.story');

    var source_index = $.inArray(story.attr('id'), StorySwapper.story_order);

    var inserted = false;

    stories.each( function() {
      destination_index = $.inArray(this.id, StorySwapper.story_order);

      var above = source_index <= destination_index;

      if (above) {
        $(this).before(story);
        inserted = true;
        return false; // break
      }
    });

    if (!inserted) ol.append(story);
  },

  convert_checkboxes: function() {
    $('input[type="checkbox"]').each( function() {
      // make links that toggle the checkboxes
      $(this).before('Move');
    });

    StorySwapper.bind_anchors();
  },

  bind_anchors: function() {
    $('a.move').click( function() {
      var id = this.href.split('#')[1];
      var input = $('input#'+id);
      input.click();
      StorySwapper.move_checkbox_story(input);
      StorySwapper.bind_anchors();
      return false;
    });
  },

  init_stories: function() {
    // store initial order
    StorySwapper.story_order = $.map($('ol li.story'), function(element, i) {
      return element.id
    });

    // move stories to correct ols - order is maintained without doing anything
    // at this stage
    $('ol li.story').each( function() {
      if ($(this).find('input[checked]:checked')[0]) {
        var story = $(this).remove();
        $('#stories_iteration ol').append(story);
      }
    });
  },

  move_checkbox_story: function(checkbox) {
    var checked_before_removal = checkbox.attr('checked');
    var story = checkbox.parents('li.story').remove();

    var append_to = checked_before_removal
      ? $('#stories_iteration ol')
      : $('#stories_available ol');

    StorySwapper.append_story(story, append_to);

    // workaround ie6 bug with checkbox values being reset after append
    if (checked_before_removal != checkbox.attr('checked')) checkbox.click();

    StorySwapper.update_estimates();
    StorySwapper.bind_estimates();
    StoryToggler.bind_anchors(story);
  },

  bind_estimates: function() {
    $('div.estimate input').keyup(StorySwapper.update_estimates);
  },

  update_estimates: function() {
    var points;
    var integer;

    $('#stories_iteration,#stories_available').each( function() {
      if ($(this).find('li.story').length == 0) {
        $(this).find('span.estimate').hide();
      } else {
        points = 0;
        $(this).find('div.estimate input').each( function() {
          integer = parseInt($(this).val());
          if (integer) points += integer;
        });
        $(this).find('span.estimate span.numeric').html(points);
        $(this).find('span.estimate').show();
      }
    });

  }
}

var StoryToggler = {
  init: function() {
    // collapse all story content
    $('.content').hide();

    // insert expand links
    $('ol li.story').each( function() {
      $(this).find('.content')
      .before('Show Story');
    });

    StoryToggler.bind_anchors();
  },

  // expand functionality for story content
  bind_anchors: function(base) {
    if (base) {
      base.find('a.expand').click(StoryToggler.toggle_content);
    } else {
      $('a.expand').click(StoryToggler.toggle_content);
    }
  },

  toggle_content: function() {
    var id = this.href.split('#')[1];
    $('#'+id+' .content').toggle();
    if ($(this).html() == 'Show Story') {
      $(this).html('Hide Story');
    } else {
      $(this).html('Show Story');
    }
    return false;
  }
}
<commit_msg>call update_estimates instead of show_hide_estimate_whatever<commit_after>function NewStoryAdder() {
  $('a#contextual_new_story').click( function() {
    new Request({
      url: this.href,
      beforeClose: function() {
        // the following attempts to recognise a story/show url
        var url_parts = this.url.split('/');
        var last_part = url_parts[url_parts.length-1];
        var rejected = $.inArray(last_part, ['stories', 'new']);
        var not_rejected = rejected == -1;

        if (not_rejected) {
          $.ajax({
            url: this.url + '/estimate',
            success: function(html, status) {
              // add the story to the available list
              $('#stories_available>ol').prepend(html)

              // re-initialise the page
              StorySwapper.init_stories();
              $('a.move').remove();
              StorySwapper.convert_checkboxes();
              StorySwapper.update_estimates();

              $('a.expand').remove();
              StoryToggler.init();
            }
          });
        }
      }
    });
    return false;
  });
}

var StorySwapper = {
  init: function() {
    // create an iteration stories div
    $('#stories_available')
      .before('

Story Points (0)
Iteration stories

');

    // wrap the available div
    var available_div = $('#stories_available').remove();
    $('#stories_iteration_container').after('

Story Points (0)'+available_div.html()+'

');

    StorySwapper.init_stories();
    StorySwapper.convert_checkboxes();
    StorySwapper.bind_estimates();
    StorySwapper.update_estimates();
  },

  // add the story to the specified ol, maintaining the original order
  append_story: function(story, ol) {
    var stories = ol.find('li.story');

    var source_index = $.inArray(story.attr('id'), StorySwapper.story_order);

    var inserted = false;

    stories.each( function() {
      destination_index = $.inArray(this.id, StorySwapper.story_order);

      var above = source_index <= destination_index;

      if (above) {
        $(this).before(story);
        inserted = true;
        return false; // break
      }
    });

    if (!inserted) ol.append(story);
  },

  convert_checkboxes: function() {
    $('input[type="checkbox"]').each( function() {
      // make links that toggle the checkboxes
      $(this).before('Move');
    });

    StorySwapper.bind_anchors();
  },

  bind_anchors: function() {
    $('a.move').click( function() {
      var id = this.href.split('#')[1];
      var input = $('input#'+id);
      input.click();
      StorySwapper.move_checkbox_story(input);
      StorySwapper.bind_anchors();
      return false;
    });
  },

  init_stories: function() {
    // store initial order
    StorySwapper.story_order = $.map($('ol li.story'), function(element, i) {
      return element.id
    });

    // move stories to correct ols - order is maintained without doing anything
    // at this stage
    $('ol li.story').each( function() {
      if ($(this).find('input[checked]:checked')[0]) {
        var story = $(this).remove();
        $('#stories_iteration ol').append(story);
      }
    });
  },

  move_checkbox_story: function(checkbox) {
    var checked_before_removal = checkbox.attr('checked');
    var story = checkbox.parents('li.story').remove();

    var append_to = checked_before_removal
      ? $('#stories_iteration ol')
      : $('#stories_available ol');

    StorySwapper.append_story(story, append_to);

    // workaround ie6 bug with checkbox values being reset after append
    if (checked_before_removal != checkbox.attr('checked')) checkbox.click();

    StorySwapper.update_estimates();
    StorySwapper.bind_estimates();
    StoryToggler.bind_anchors(story);
  },

  bind_estimates: function() {
    $('div.estimate input').keyup(StorySwapper.update_estimates);
  },

  update_estimates: function() {
    var points;
    var integer;

    $('#stories_iteration,#stories_available').each( function() {
      if ($(this).find('li.story').length == 0) {
        $(this).find('span.estimate').hide();
      } else {
        points = 0;
        $(this).find('div.estimate input').each( function() {
          integer = parseInt($(this).val());
          if (integer) points += integer;
        });
        $(this).find('span.estimate span.numeric').html(points);
        $(this).find('span.estimate').show();
      }
    });

  }
}

var StoryToggler = {
  init: function() {
    // collapse all story content
    $('.content').hide();

    // insert expand links
    $('ol li.story').each( function() {
      $(this).find('.content')
      .before('Show Story');
    });

    StoryToggler.bind_anchors();
  },

  // expand functionality for story content
  bind_anchors: function(base) {
    if (base) {
      base.find('a.expand').click(StoryToggler.toggle_content);
    } else {
      $('a.expand').click(StoryToggler.toggle_content);
    }
  },

  toggle_content: function() {
    var id = this.href.split('#')[1];
    $('#'+id+' .content').toggle();
    if ($(this).html() == 'Show Story') {
      $(this).html('Hide Story');
    } else {
      $(this).html('Show Story');
    }
    return false;
  }
}
<|endoftext|>


<commit_before><commit_msg>add function jqScrollRestoreScroll<commit_after><|endoftext|>


<commit_before>angular.module('MainCtrl', ['MainService']).controller('MainController', ['$scope', 'PiCheck', function($scope, PiCheck) {

  $scope.test = 'It works!';
  $scope.index = 0;
  $scope.digit = 0;
  $scope.correctDigit = true;

  $scope.update = function(piInput) {
    $scope.piDigit = PiCheck.checkDigit($scope.index);
    if($scope.piDigit === piInput.slice(-1)) {
      console.log('Matching digit');
    } else {
      console.log('Incorrect digit');
      $scope.correctDigit = false;
      angular.element(document.getElementById('pi-input')).prop('disabled', true);
    }
    $scope.index++;
    if($scope.index < 2) {
      $scope.digit = $scope.index;
    } else {
      $scope.digit = $scope.index - 1;
    }
  };

  console.log(PiCheck.test());

}]);
<commit_msg>Fixed issue with counter adding 1 after incorrect digit is entered<commit_after>angular.module('MainCtrl', ['MainService']).controller('MainController', ['$scope', 'PiCheck', function($scope, PiCheck) {

  $scope.test = 'It works!';
  $scope.index = 0;
  $scope.digit = 0;
  $scope.correctDigit = true;

  $scope.update = function(piInput) {
    $scope.piDigit = PiCheck.checkDigit($scope.index);
    if($scope.piDigit === piInput.slice(-1)) {
      console.log('Matching digit');
    } else {
      console.log('Incorrect digit');
      $scope.correctDigit = false;
      angular.element(document.getElementById('pi-input')).prop('disabled', true);
      $scope.index--;
    }
    $scope.index++;
    if($scope.index < 2) {
      $scope.digit = $scope.index;
    } else {
      $scope.digit = $scope.index - 1;
    }
  };

  console.log(PiCheck.test());

}]);
<|endoftext|>


<commit_before>/*
 * @fileOverview Background service running for the wallet
 */
require(['backend/port',
         'backend/services/lobby',
         'backend/services/obelisk',
         'backend/services/wallet',
         'backend/services/gui',
         'backend/services/ticker',
         'backend/services/mixer',
         'backend/services/notifier',
         'backend/services/ctxmenus'],
function(Port, LobbyService, ObeliskService, WalletService, GuiService, TickerService, MixerService, NotifierService, CtxMenusService) {

function DarkWalletService() {

    var self = this;

    // Backend services
    var services = {
        obelisk: new ObeliskService(this),
        wallet: new WalletService(this),
        ctxMenus: new CtxMenusService(this),
        gui: new GuiService(this),
        ticker: new TickerService(this),
        mixer: new MixerService(this),
        notifier: new NotifierService(this),
        lobby: new LobbyService(this)
    };

    // Public API
    this.service = this.serviceGetter(services);

    var servicesStatus = { gateway: 'offline', obelisk: 'offline' };
    this.servicesStatus = servicesStatus;

    /***************************************
    /* Hook up some utility functions
     */

    this.loadIdentity = function(idx) {
        return services.wallet.loadIdentity(idx);
    };

    // Get an identity from the keyring
    this.getIdentity = function(idx) {
        return services.wallet.getIdentity(idx);
    };
    this.getCurrentIdentity = function() {
        return services.wallet.getCurrentIdentity();
    };
    this.getLobbyTransport = function() {
        return services.lobby.getLobbyTransport();
    };

    // Start up history for an address
    this.initAddress = function(walletAddress) { return services.wallet.initAddress(walletAddress); }

    /***************************************
    /* Global communications
     */

    Port.connect('wallet', function(data) {
        // wallet closing
        if (data.type == 'closing') {
            services['obelisk'].disconnect();
        }
    });

    this.connect = function(connectUri) {
        var identity = services.wallet.getCurrentIdentity();
        connectUri = connectUri || identity.connections.servers[identity.connections.selectedServer].address || 'wss://gateway.unsystem.net';
        servicesStatus.gateway = 'connecting';
        services.obelisk.connect(connectUri, function(err) {
            if (err) {
                servicesStatus.gateway = 'error';
            } else {
                servicesStatus.gateway = 'ok';
                services.wallet.handleInitialConnect();
            }
        });
    };
    this.getKeyRing = function() {
        return services.wallet.getKeyRing();
    };

    this.getClient = function() {
        return services.obelisk.getClient();
    };

    this.getServices = function() {
        return self.service;
    };
}

/**
 * Fills an object with service getters
 * @param {Object} services Object that contains the real services
 * @private
 */
DarkWalletService.prototype.serviceGetter = function(services) {
    var getters = {};
    for(var i in services) {
        Object.defineProperty(getters, i, {
            get: function() {
                var j = services[i];
                return function() {
                    return j;
                };
            }()
        });
    };
    return getters;
};

/***************************************
/* Communications
 */
var sendInternalMessage = function(msg) {
    chrome.runtime.sendMessage(chrome.runtime.id, msg);
};

var addListener = function(callback) {
    chrome.runtime.onMessage.addListener(callback);
};

/***************************************
/* Service instance that will be running in the background page
 */
var service = new DarkWalletService();

/***************************************
/* Bindings for the page window so we can have easy access
 */

window.connect = function(_server) { return service.connect(_server); };

window.loadIdentity = service.loadIdentity;
window.getIdentity = function(idx) { return service.getIdentity(idx); };
window.getCurrentIdentity = service.getCurrentIdentity;

window.getKeyRing = service.getKeyRing;
window.servicesStatus = service.servicesStatus;
window.getLobbyTransport = service.getLobbyTransport;

window.getClient = service.getClient;
window.getServices = service.getServices;

window.initAddress = function(_w) {return service.initAddress(_w);};

window.addListener = addListener;
window.sendInternalMessage = sendInternalMessage;
});

<commit_msg>Set a more informative name to the function initializing the services array.<commit_after>/*
 * @fileOverview Background service running for the wallet
 */
require(['backend/port',
         'backend/services/lobby',
         'backend/services/obelisk',
         'backend/services/wallet',
         'backend/services/gui',
         'backend/services/ticker',
         'backend/services/mixer',
         'backend/services/notifier',
         'backend/services/ctxmenus'],
function(Port, LobbyService, ObeliskService, WalletService, GuiService, TickerService, MixerService, NotifierService, CtxMenusService) {

function DarkWalletService() {

    var self = this;

    // Backend services
    var services = {
        obelisk: new ObeliskService(this),
        wallet: new WalletService(this),
        ctxMenus: new CtxMenusService(this),
        gui: new GuiService(this),
        ticker: new TickerService(this),
        mixer: new MixerService(this),
        notifier: new NotifierService(this),
        lobby: new LobbyService(this)
    };

    // Public API
    this.service = this.initializeServices(services);

    var servicesStatus = { gateway: 'offline', obelisk: 'offline' };
    this.servicesStatus = servicesStatus;

    /***************************************
    /* Hook up some utility functions
     */

    this.loadIdentity = function(idx) {
        return services.wallet.loadIdentity(idx);
    };

    // Get an identity from the keyring
    this.getIdentity = function(idx) {
        return services.wallet.getIdentity(idx);
    };
    this.getCurrentIdentity = function() {
        return services.wallet.getCurrentIdentity();
    };
    this.getLobbyTransport = function() {
        return services.lobby.getLobbyTransport();
    };

    // Start up history for an address
    this.initAddress = function(walletAddress) { return services.wallet.initAddress(walletAddress); }

    /***************************************
    /* Global communications
     */

    Port.connect('wallet', function(data) {
        // wallet closing
        if (data.type == 'closing') {
            services['obelisk'].disconnect();
        }
    });

    this.connect = function(connectUri) {
        var identity = services.wallet.getCurrentIdentity();
        connectUri = connectUri || identity.connections.servers[identity.connections.selectedServer].address || 'wss://gateway.unsystem.net';
        servicesStatus.gateway = 'connecting';
        services.obelisk.connect(connectUri, function(err) {
            if (err) {
                servicesStatus.gateway = 'error';
            } else {
                servicesStatus.gateway = 'ok';
                services.wallet.handleInitialConnect();
            }
        });
    };
    this.getKeyRing = function() {
        return services.wallet.getKeyRing();
    };

    this.getClient = function() {
        return services.obelisk.getClient();
    };

    this.getServices = function() {
        return self.service;
    };
}

/**
 * Fills an object with service getters
 * @param {Object} services Object that contains the real services
 * @private
 */
DarkWalletService.prototype.initializeServices = function(services) {
    var getters = {};
    for(var i in services) {
        Object.defineProperty(getters, i, {
            get: function() {
                var j = services[i];
                return function() {
                    return j;
                };
            }()
        });
    };
    return getters;
};

/***************************************
/* Communications
 */
var sendInternalMessage = function(msg) {
    chrome.runtime.sendMessage(chrome.runtime.id, msg);
};

var addListener = function(callback) {
    chrome.runtime.onMessage.addListener(callback);
};

/***************************************
/* Service instance that will be running in the background page
 */
var service = new DarkWalletService();

/***************************************
/* Bindings for the page window so we can have easy access
 */

window.connect = function(_server) { return service.connect(_server); };

window.loadIdentity = service.loadIdentity;
window.getIdentity = function(idx) { return service.getIdentity(idx); };
window.getCurrentIdentity = service.getCurrentIdentity;

window.getKeyRing = service.getKeyRing;
window.servicesStatus = service.servicesStatus;
window.getLobbyTransport = service.getLobbyTransport;

window.getClient = service.getClient;
window.getServices = service.getServices;

window.initAddress = function(_w) {return service.initAddress(_w);};

window.addListener = addListener;
window.sendInternalMessage = sendInternalMessage;
});

<|endoftext|>


<commit_before>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-nodeunit');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-type');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-less');

  /*
   grunt.loadNpmTasks('grunt-typescript');
   */

  // Project configuration.
  var port = grunt.option('webapp_port');
  var webapp_outdir = grunt.option('webapp_outdir');

  if (!port) {
    port = 8181;
  }

  grunt.task.registerTask('clean-appjs', 'Clean up generated app.js file', function() {
    var file = webapp_outdir + "/app/app.js";
    grunt.log.writeln("Cleaning up " + file);
    grunt.file.delete(file, { force: true });
  });

  var appFiles = ['src/main/d.ts/*.ts', 'src/main/webapp/app/**/*.ts'];

  grunt.initConfig({
    test:{
      files:['src/test/js/**/*.js']
    },
    type:{
      compile:{
        files: [
          {
            src: appFiles,
            dest: "<%= grunt.option('webapp_outdir') %>/app/app.js"
          }
        ],
        options:{
          sourcemap: false,
          target: 'es5',
          //module:'amd',
          style:'eqeqeq;bitwise'
        }
      }
    },
    less: {
      options: {
        paths: ['src/main/webapp/css']
      },
      src: {
        expand: true,
        cwd: 'src/main/webapp/css',
        src: '*.less',
        ext: '.css',
        dest: "<%= grunt.option('webapp_outdir') %>/css"
      }

    },
    copy:{
      dist: {
        files: [
          {
            expand: true,
            cwd: "src/main/webapp/",
            src: ["./**"],
            dest: "<%= grunt.option('webapp_outdir') %>/"
          }
        ]
      },
      test: {
        files: [
          {
            expand: true,
            cwd: "<%= grunt.option('webapp_outdir') %>/",
            src: ["./**"],
            dest: "src/test/unit/"
          }]
      }
    },
    concat: {
      main: {
        src: ["target/schema/js/*.js", "<%= grunt.option('webapp_outdir') %>/app/app.js"],
        dest: "<%= grunt.option('webapp_outdir') %>/app/app.js"
      }
    },
    watch: {
      app: {
        files: ["src/main/webapp/**", "target/schema/js/*.js"],
        tasks: ['clean-appjs', 'type', 'concat', 'copy:dist'],
        options: {
          livereload: true
        }
      }
    }
  });

  // Default task.
  grunt.registerTask('default', ['clean-appjs', 'type', 'concat', 'copy', 'less']);

  // watch source for changes
  grunt.registerTask('watchSrc', ['clean-appjs', 'type', 'concat', 'copy', 'less', 'watch']);

};
<commit_msg>Compile less during watch task<commit_after>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-nodeunit');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-type');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-less');

  /*
   grunt.loadNpmTasks('grunt-typescript');
   */

  // Project configuration.
  var port = grunt.option('webapp_port');
  var webapp_outdir = grunt.option('webapp_outdir');

  if (!port) {
    port = 8181;
  }

  grunt.task.registerTask('clean-appjs', 'Clean up generated app.js file', function() {
    var file = webapp_outdir + "/app/app.js";
    grunt.log.writeln("Cleaning up " + file);
    grunt.file.delete(file, { force: true });
  });

  var appFiles = ['src/main/d.ts/*.ts', 'src/main/webapp/app/**/*.ts'];

  grunt.initConfig({
    test:{
      files:['src/test/js/**/*.js']
    },
    type:{
      compile:{
        files: [
          {
            src: appFiles,
            dest: "<%= grunt.option('webapp_outdir') %>/app/app.js"
          }
        ],
        options:{
          sourcemap: false,
          target: 'es5',
          //module:'amd',
          style:'eqeqeq;bitwise'
        }
      }
    },
    less: {
      options: {
        paths: ['src/main/webapp/css']
      },
      src: {
        expand: true,
        cwd: 'src/main/webapp/css',
        src: '*.less',
        ext: '.css',
        dest: "<%= grunt.option('webapp_outdir') %>/css"
      }

    },
    copy:{
      dist: {
        files: [
          {
            expand: true,
            cwd: "src/main/webapp/",
            src: ["./**"],
            dest: "<%= grunt.option('webapp_outdir') %>/"
          }
        ]
      },
      test: {
        files: [
          {
            expand: true,
            cwd: "<%= grunt.option('webapp_outdir') %>/",
            src: ["./**"],
            dest: "src/test/unit/"
          }]
      }
    },
    concat: {
      main: {
        src: ["target/schema/js/*.js", "<%= grunt.option('webapp_outdir') %>/app/app.js"],
        dest: "<%= grunt.option('webapp_outdir') %>/app/app.js"
      }
    },
    watch: {
      app: {
        files: ["src/main/webapp/**", "target/schema/js/*.js"],
        tasks: ['clean-appjs', 'type', 'concat', 'copy:dist', 'less'],
        options: {
          livereload: true
        }
      }
    }
  });

  // Default task.
  grunt.registerTask('default', ['clean-appjs', 'type', 'concat', 'copy', 'less']);

  // watch source for changes
  grunt.registerTask('watchSrc', ['clean-appjs', 'type', 'concat', 'copy', 'less', 'watch']);

};
<|endoftext|>


<commit_before>var mrf24j40 = require('node-mrf24j40');
var MRF24J40 = mrf24j40.MRF24J40;
var ControlRegister = mrf24j40.ControlRegister;
var FIFO = mrf24j40.FIFO;

var osnp = require('node-osnp');
var FrameType = osnp.FrameType;
var FrameVersion = osnp.FrameVersion;
var AddressingMode = osnp.AddressingMode;
var MACCommand = osnp.MACCommand;

var radio;
var frameQueue = [];
var cbCache = {};
var transmissionPending = null;

var deviceDiscoveryPeriods;
var discoveryCallback;
var pairingCallback;
var unpairingCallback;

var nextFreeShortAddress;

exports.start = function() {
  if (process.platform == 'linux') {
    radio = new MRF24J40('raspi');
  }

  // This must be persistent and must use a list instead
  nextFreeShortAddress = 0x0001;

  osnp.setPANID(new Buffer([0xfe, 0xca]));
  osnp.setShortAddress(new Buffer([0x00, 0x00]));

  if (radio) {
    radio.on('frame', handleReceived);
    radio.on('transmitted', handleTransmitted);
    radio.initialize();
    radio.setPANCoordinator();
    radio.setPANID(osnp.getPANID());
    radio.setShortAddress(osnp.getShortAddress());
    radio.setChannel(2);
  }
}

exports.pair = function(device, pairingData, cb) {
  pairingCallback = cb.bind(device);
  var frameControlLow = osnp.makeFrameControlLow(FrameType.MAC_CMD, false, false, true, false);
  var frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.EUI, FrameVersion.V2003, AddressingMode.NOT_PRESENT);

  var frame = osnp.createFrame(frameControlLow, frameControlHigh);
  frame.destinationAddress = device.protocolInfo.eui;

  device.protocolInfo.shortAddress = new Buffer(2);
  device.protocolInfo.shortAddress.writeUInt16LE(nextFreeShortAddress++);

  frame.payload = new Buffer([MACCommand.DISASSOCIATED, device.protocolInfo.shortAddress[0], device.protocolInfo.shortAddress[1]]);
  frameQueue.push(frame);
  trySend();
}

exports.unpair = function(device, cb) {
  unpairingCallback = cb.bind(device);
  var frameControlLow = osnp.makeFrameControlLow(FrameType.MAC_CMD, false, false, true, false);
  var frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.SHORT_ADDRESS, FrameVersion.V2003, AddressingMode.NOT_PRESENT);

  var frame = osnp.createFrame(frameControlLow, frameControlHigh);
  frame.destinationAddress = device.protocolInfo.shortAddress;
  frame.payload = new Buffer([MACCommand.DISASSOCIATED]);
  frameQueue.push(frame);
  trySend();
}

exports.discoverDevices = function(cb) {
  deviceDiscoveryPeriods = 0;
  discoveryCallback = cb;

  sendDiscoveryFrame();
}

exports.send = function(device, data, cb) {
  var frameControlLow = osnp.makeFrameControlLow(FrameType.DATA, false, false, true, false);
  var frameControlHigh;

  if (device.paired) {
    frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.SHORT_ADDRESS, FrameVersion.V2003, AddressingMode.NOT_PRESENT);
  } else {
    frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.EUI, FrameVersion.V2003, AddressingMode.SHORT_ADDRESS);
  }

  var frame = osnp.createFrame(frameControlLow, frameControlHigh);

  if (device.paired) {
    frame.destinationAddress = device.protocolInfo.shortAddress;
  } else {
    frame.destinationPAN = new Buffer([0x00, 0x00]);
    frame.destinationAddress = device.protocolInfo.eui;
  }

  frame.payload = data;

  frameQueue.push(frame);
  cbCache[frame.destinationAddress.toString('hex')] = cb;
  trySend();
}

function sendDiscoveryFrame() {
  var frameControlLow = osnp.makeFrameControlLow(FrameType.MAC_CMD, false, false, false, false);
  var frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.SHORT_ADDRESS, FrameVersion.V2003, AddressingMode.SHORT_ADDRESS);

  var frame = osnp.createFrame(frameControlLow, frameControlHigh);
  frame.destinationPAN = new Buffer([0x00, 0x00]);
  frame.destinationAddress = new Buffer([0xff, 0xff]);
  frame.payload = new Buffer([MACCommand.DISCOVER]);
  frameQueue.push(frame);
  trySend();

  if (deviceDiscoveryPeriods < 100) {
    deviceDiscoveryPeriods++;
    setTimeout(sendDiscoveryFrame, 100);
  }
}

function trySend() {
  if (!transmissionPending && (frameQueue.length > 0)) {
    var frame = frameQueue.shift();
    transmissionPending = frame;
    var frameLength = frame.getEncodedLength();
    var buf = new Buffer(frameLength + 2);
    buf[0] = frameLength - frame.payload.length;
    buf[1] = frameLength;
    frame.encode(buf.slice(2));
    radio.transmit(buf);
  }
}

function handleMACFrame(frame) {
  switch (frame.payload[0]) {
  case MACCommand.ASSOCIATION_RESPONSE:
    pairingCallback();
    break;
  case MACCommand.DATA_REQUEST:
    break;
  case MACCommand.DISCOVER:
    discoveryCallback(new OSNPProtocolInfo(frame.sourceAddress));
    break;
  }
}

function handleDataFrame(frame) {
  var cb = cbCache[frame.sourceAddress.toString('hex')];

  //TODO: what to do with data generated by the device (notification)
  if (cb) {
    delete cbCache[frame.sourceAddress.toString('hex')];
    cb(frame.payload);
  }
}

function handleReceived(rawFrame, lqi, rssi) {
  var frame = osnp.parseFrame(rawFrame);

  switch(frame.getFrameType()) {
  case FrameType.MAC_CMD:
    handleMACFrame(frame);
    break;
  case FrameType.DATA:
    handleDataFrame(frame);
    break;
  }
}

function handleTransmitted(txErr, ccaErr) {
  if(ccaErr) {
    frameQueue.push(transmissionPending);
  } else if (txErr) {
    delete cbCache[transmissionPending.destinationAddress.toString('hex')];
  } else if (transmissionPending.payload[0] == MACCommand.DISASSOCIATED) {
    unpairingCallback();
    unpairingCallback = null;
  }

  transmissionPending = null;
  trySend();
}

function OSNPProtocolInfo(eui) {
  this.eui = eui;
  this.shortAddress = null;
  this.capabilities = null;
}

OSNPProtocolInfo.prototype.toID = function() {
  return this.eui.toString('hex');
}

<commit_msg>increased timeout and repeat<commit_after>var mrf24j40 = require('node-mrf24j40');
var MRF24J40 = mrf24j40.MRF24J40;
var ControlRegister = mrf24j40.ControlRegister;
var FIFO = mrf24j40.FIFO;

var osnp = require('node-osnp');
var FrameType = osnp.FrameType;
var FrameVersion = osnp.FrameVersion;
var AddressingMode = osnp.AddressingMode;
var MACCommand = osnp.MACCommand;

var radio;
var frameQueue = [];
var cbCache = {};
var transmissionPending = null;

var deviceDiscoveryPeriods;
var discoveryCallback;
var pairingCallback;
var unpairingCallback;

var nextFreeShortAddress;

exports.start = function() {
  if (process.platform == 'linux') {
    radio = new MRF24J40('raspi');
  }

  // This must be persistent and must use a list instead
  nextFreeShortAddress = 0x0001;

  osnp.setPANID(new Buffer([0xfe, 0xca]));
  osnp.setShortAddress(new Buffer([0x00, 0x00]));

  if (radio) {
    radio.on('frame', handleReceived);
    radio.on('transmitted', handleTransmitted);
    radio.initialize();
    radio.setPANCoordinator();
    radio.setPANID(osnp.getPANID());
    radio.setShortAddress(osnp.getShortAddress());
    radio.setChannel(2);
  }
}

exports.pair = function(device, pairingData, cb) {
  pairingCallback = cb.bind(device);
  var frameControlLow = osnp.makeFrameControlLow(FrameType.MAC_CMD, false, false, true, false);
  var frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.EUI, FrameVersion.V2003, AddressingMode.NOT_PRESENT);

  var frame = osnp.createFrame(frameControlLow, frameControlHigh);
  frame.destinationAddress = device.protocolInfo.eui;

  device.protocolInfo.shortAddress = new Buffer(2);
  device.protocolInfo.shortAddress.writeUInt16LE(nextFreeShortAddress++);

  frame.payload = new Buffer([MACCommand.DISASSOCIATED, device.protocolInfo.shortAddress[0], device.protocolInfo.shortAddress[1]]);
  frameQueue.push(frame);
  trySend();
}

exports.unpair = function(device, cb) {
  unpairingCallback = cb.bind(device);
  var frameControlLow = osnp.makeFrameControlLow(FrameType.MAC_CMD, false, false, true, false);
  var frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.SHORT_ADDRESS, FrameVersion.V2003, AddressingMode.NOT_PRESENT);

  var frame = osnp.createFrame(frameControlLow, frameControlHigh);
  frame.destinationAddress = device.protocolInfo.shortAddress;
  frame.payload = new Buffer([MACCommand.DISASSOCIATED]);
  frameQueue.push(frame);
  trySend();
}

exports.discoverDevices = function(cb) {
  deviceDiscoveryPeriods = 0;
  discoveryCallback = cb;

  sendDiscoveryFrame();
}

exports.send = function(device, data, cb) {
  var frameControlLow = osnp.makeFrameControlLow(FrameType.DATA, false, false, true, false);
  var frameControlHigh;

  if (device.paired) {
    frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.SHORT_ADDRESS, FrameVersion.V2003, AddressingMode.NOT_PRESENT);
  } else {
    frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.EUI, FrameVersion.V2003, AddressingMode.SHORT_ADDRESS);
  }

  var frame = osnp.createFrame(frameControlLow, frameControlHigh);

  if (device.paired) {
    frame.destinationAddress = device.protocolInfo.shortAddress;
  } else {
    frame.destinationPAN = new Buffer([0x00, 0x00]);
    frame.destinationAddress = device.protocolInfo.eui;
  }

  frame.payload = data;

  frameQueue.push(frame);
  cbCache[frame.destinationAddress.toString('hex')] = cb;
  trySend();
}

function sendDiscoveryFrame() {
  var frameControlLow = osnp.makeFrameControlLow(FrameType.MAC_CMD, false, false, false, false);
  var frameControlHigh = osnp.makeFrameControlHigh(AddressingMode.SHORT_ADDRESS, FrameVersion.V2003, AddressingMode.SHORT_ADDRESS);

  var frame = osnp.createFrame(frameControlLow, frameControlHigh);
  frame.destinationPAN = new Buffer([0x00, 0x00]);
  frame.destinationAddress = new Buffer([0xff, 0xff]);
  frame.payload = new Buffer([MACCommand.DISCOVER]);
  frameQueue.push(frame);
  trySend();

  if (deviceDiscoveryPeriods < 1000) {
    deviceDiscoveryPeriods++;
    setTimeout(sendDiscoveryFrame, 250);
  }
}

function trySend() {
  if (!transmissionPending && (frameQueue.length > 0)) {
    var frame = frameQueue.shift();
    transmissionPending = frame;
    var frameLength = frame.getEncodedLength();
    var buf = new Buffer(frameLength + 2);
    buf[0] = frameLength - frame.payload.length;
    buf[1] = frameLength;
    frame.encode(buf.slice(2));
    radio.transmit(buf);
  }
}

function handleMACFrame(frame) {
  switch (frame.payload[0]) {
  case MACCommand.ASSOCIATION_RESPONSE:
    pairingCallback();
    break;
  case MACCommand.DATA_REQUEST:
    break;
  case MACCommand.DISCOVER:
    discoveryCallback(new OSNPProtocolInfo(frame.sourceAddress));
    break;
  }
}

function handleDataFrame(frame) {
  var cb = cbCache[frame.sourceAddress.toString('hex')];

  //TODO: what to do with data generated by the device (notification)
  if (cb) {
    delete cbCache[frame.sourceAddress.toString('hex')];
    cb(frame.payload);
  }
}

function handleReceived(rawFrame, lqi, rssi) {
  var frame = osnp.parseFrame(rawFrame);

  switch(frame.getFrameType()) {
  case FrameType.MAC_CMD:
    handleMACFrame(frame);
    break;
  case FrameType.DATA:
    handleDataFrame(frame);
    break;
  }
}

function handleTransmitted(txErr, ccaErr) {
  if(ccaErr) {
    frameQueue.push(transmissionPending);
  } else if (txErr) {
    delete cbCache[transmissionPending.destinationAddress.toString('hex')];
  } else if (transmissionPending.payload[0] == MACCommand.DISASSOCIATED) {
    unpairingCallback();
    unpairingCallback = null;
  }

  transmissionPending = null;
  trySend();
}

function OSNPProtocolInfo(eui) {
  this.eui = eui;
  this.shortAddress = null;
  this.capabilities = null;
}

OSNPProtocolInfo.prototype.toID = function() {
  return this.eui.toString('hex');
}

<|endoftext|>


<commit_before>'use strict';
nwmApplication.service('CanvasService', ['$routeParams', '$window', 'SocketIoService', 'UserService', 'Utils', 'FabricService', 'ListenerService', function ($routeParams, $window, SocketIoService, UserService, Utils, FabricService, ListenerService) {
    var self = this;
    var canvasToolOptions = [
        {name: 'None', glyphiconicon: 'glyphicon-off', active: false, fn: canvasToolNone, help: 'Deactivate any tool'},
        {name: 'Write', glyphiconicon: 'glyphicon-font', active: false, fn: canvasToolWrite, help: 'Write text'},
        {name: 'Draw', glyphiconicon: 'glyphicon-pencil', active: false, fn: canvasToolDraw, help: 'Free draw with pencil'},
        {name: 'Rectangle', glyphiconicon: 'glyphicon-unchecked', active: false, fn: canvasToolRect, help:'Add rectangle'},
        {name: 'Arrow', glyphiconicon: 'glyphicon-arrow-right', active: false, fn: canvasToolArrow, help: 'Add arrow'},
        {name: 'Duplicate', glyphiconicon: 'glyphicon-duplicate', active: false, fn: duplicateObject, help: 'Duplicate any object'},
        {name: 'Group/Ungroup', glyphiconicon: 'glyphicon-magnet', active: false, fn: groupUngroupObjects, help: 'Group or Ungroup objects'}
    ];

    this.start = function () {
        FabricService.createCanvas();
        FabricService.pimpFabricPrototypes();
        SocketIoService.send().joinRoom(UserService.user());
        ListenerService.bindListeners();
        FabricService.selectionCreated(selectionCreated);
        FabricService.selectionCleared(selectionCleared);
        function selectionCreated(options) {
            if(options.target.type === 'group') {
                ListenerService.attachListenersToFabricObject(options.target);
            }
        }

        function selectionCleared(options){
            if(options.target.type === 'group') {
                ListenerService.removeAllListeners(options.target);
            }
        }
    };

    function groupUngroupObjects(){
        var activeGroup = FabricService.canvas().getActiveGroup();
        var activeObject = FabricService.canvas().getActiveObject();
        if(activeGroup && !activeGroup.isPersistent){
            var group = FabricService.group(activeGroup);
            ListenerService.attachListenersToFabricObject(group);
        }else if(activeObject && activeObject.isPersistent){
            ListenerService.removeAllListeners(activeObject);
            FabricService.ungroup(activeObject);
        }

        self.setActiveCanvasTool('None');
    }

    function duplicateObject(){
        var fabricObject = FabricService.canvas().getActiveObject();
        if(fabricObject){
            var clonedFabricObject = fabric.util.object.clone(fabricObject);
            correctPosition(clonedFabricObject, fabricObject);
            clonedFabricObject.objectId = Utils.guid();
            ListenerService.removeAllListeners(clonedFabricObject);
            ListenerService.attachListenersToFabricObject(clonedFabricObject);
            FabricService.canvas().add(clonedFabricObject).renderAll();
            sendOverWire(clonedFabricObject);
        }

        function correctPosition(clonedFabricObject, fabricObject) {
            var random = Math.floor((Math.random() * 50) + 1);
            clonedFabricObject.set("top", fabricObject.top + random);
            clonedFabricObject.set("left", fabricObject.left + random);
        }

        function sendOverWire(clonedFabricObject) {
            var json = JSON.stringify(clonedFabricObject);
            SocketIoService.send().addObject(json);
        }
        self.setActiveCanvasTool('None');

    };
    this.getCanvasAsBase64 = function(imagetype){
        return FabricService.canvas().toDataURL(imagetype);
    };
    this.canvasTools = function () {
        return canvasToolOptions;
    };
    this.saveCanvas = function(){
        SocketIoService.send().saveCanvas(
            {
                randomString: UserService.user().randomString,
                room: UserService.user().room,
                canvas: JSON.stringify(FabricService.canvas().toJSON(['timestamp']))
            });
    };
    function canvasToolNone() {
        FabricService.canvas().isDrawingMode = false;
        FabricService.removeMouseDown();
        FabricService.removePathCreated();
    }

    function canvasToolWrite() {
        FabricService.mouseDown(iTextMouseDown);
        function iTextMouseDown(options) {
            if (!options.target) {
                var iText = FabricService.createItext(options);
                createAndSyncFrom(iText);
                ListenerService.attachListenersToFabricObject(iText);
                iText.enterEditing();
                iText.selectionStart = 0;
                iText.selectionEnd = iText.text.length;
                self.setActiveCanvasTool('None');
                FabricService.canvas().renderAll();
            }
        }
    }

    function canvasToolRect() {
        FabricService.mouseDown(rectMouseDown);
        function rectMouseDown(options) {
            if (!options.target) {
                var rect = FabricService.createRect(options);
                createAndSyncFrom(rect);
                ListenerService.attachListenersToFabricObject(rect);
                self.setActiveCanvasTool('None');
                FabricService.canvas().renderAll();
            }
        }
    }

    function canvasToolDraw() {
        FabricService.canvas().isDrawingMode = true;
        FabricService.pathCreated(drawPath);
        function drawPath(options) {
            var fabricObject = options.path;
            fabricObject.objectId = Utils.guid();
            var fabricObjectJson = JSON.stringify(fabricObject);
            SocketIoService.send().addObject(fabricObjectJson);
            ListenerService.attachListenersToFabricObject(fabricObject)
        }
    }

    function canvasToolArrow() {
        FabricService.mouseDown(createArrow);

        function createArrow(options) {
            if (!options.target) {
                var arrow = FabricService.createArrow(options);
                createAndSyncFrom(arrow);
                ListenerService.attachListenersToFabricObject(arrow);
                self.setActiveCanvasTool('None');
                FabricService.canvas().renderAll();
            }
        }
    }

    function createAndSyncFrom(fabricObject) {
        var json = JSON.stringify(fabricObject);
        SocketIoService.send().addObject(json);
        FabricService.canvas().calcOffset();
        FabricService.canvas().add(fabricObject);
        FabricService.canvas().setActiveObject(fabricObject);
    }

    this.findActiveCanvasTool = function () {
        return canvasToolOptions.filter(function (tool) {
            if (tool.active) {
                return true;
            }
            return false;
        })[0];
    }
    this.findCanvasTool = function (name) {
        return canvasToolOptions.filter(function (tool) {
            if (tool.name === name) {
                return true;
            }
            return false;
        })[0];
    }
    this.setActiveCanvasTool = function (name) {
        var activeCanvasTool = this.findActiveCanvasTool();
        if (activeCanvasTool) {
            if (!name || activeCanvasTool.name === name) {
                return;
            }
            activeCanvasTool.active = false;
        }
        var tool = this.findCanvasTool(name);
        tool.active = true;
        tool.fn();
    }
    this.isDrawingMode = function (value) {
        FabricService.canvas().isDrawingMode = value;
    }
    this.calculateOffset = function () {
        FabricService.canvas().calcOffset();
    }

}])<commit_msg>added todo<commit_after>'use strict';
nwmApplication.service('CanvasService', ['$routeParams', '$window', 'SocketIoService', 'UserService', 'Utils', 'FabricService', 'ListenerService', function ($routeParams, $window, SocketIoService, UserService, Utils, FabricService, ListenerService) {
    var self = this;
    var canvasToolOptions = [
        {name: 'None', glyphiconicon: 'glyphicon-off', active: false, fn: canvasToolNone, help: 'Deactivate any tool'},
        {name: 'Write', glyphiconicon: 'glyphicon-font', active: false, fn: canvasToolWrite, help: 'Write text'},
        {name: 'Draw', glyphiconicon: 'glyphicon-pencil', active: false, fn: canvasToolDraw, help: 'Free draw with pencil'},
        {name: 'Rectangle', glyphiconicon: 'glyphicon-unchecked', active: false, fn: canvasToolRect, help:'Add rectangle'},
        {name: 'Arrow', glyphiconicon: 'glyphicon-arrow-right', active: false, fn: canvasToolArrow, help: 'Add arrow'},
        {name: 'Duplicate', glyphiconicon: 'glyphicon-duplicate', active: false, fn: duplicateObject, help: 'Duplicate any object'},
        {name: 'Group/Ungroup', glyphiconicon: 'glyphicon-magnet', active: false, fn: groupUngroupObjects, help: 'Group or Ungroup objects'}
    ];

    this.start = function () {
        FabricService.createCanvas();
        FabricService.pimpFabricPrototypes();
        SocketIoService.send().joinRoom(UserService.user());
        ListenerService.bindListeners();
        FabricService.selectionCreated(selectionCreated);
        FabricService.selectionCleared(selectionCleared);
        function selectionCreated(options) {
            if(options.target.type === 'group') {
                ListenerService.attachListenersToFabricObject(options.target);
            }
        }

        function selectionCleared(options){
            if(options.target.type === 'group') {
                ListenerService.removeAllListeners(options.target);
            }
        }
    };

    function groupUngroupObjects(){
        var activeGroup = FabricService.canvas().getActiveGroup();
        var activeObject = FabricService.canvas().getActiveObject();
        if(activeGroup && !activeGroup.isPersistent){
            //TODO: if adding group to group..
            var group = FabricService.group(activeGroup);
            ListenerService.attachListenersToFabricObject(group);
        }else if(activeObject && activeObject.isPersistent){
            ListenerService.removeAllListeners(activeObject);
            FabricService.ungroup(activeObject);
        }

        self.setActiveCanvasTool('None');
    }

    function duplicateObject(){
        var fabricObject = FabricService.canvas().getActiveObject();
        if(fabricObject){
            var clonedFabricObject = fabric.util.object.clone(fabricObject);
            correctPosition(clonedFabricObject, fabricObject);
            clonedFabricObject.objectId = Utils.guid();
            ListenerService.removeAllListeners(clonedFabricObject);
            ListenerService.attachListenersToFabricObject(clonedFabricObject);
            FabricService.canvas().add(clonedFabricObject).renderAll();
            sendOverWire(clonedFabricObject);
        }

        function correctPosition(clonedFabricObject, fabricObject) {
            var random = Math.floor((Math.random() * 50) + 1);
            clonedFabricObject.set("top", fabricObject.top + random);
            clonedFabricObject.set("left", fabricObject.left + random);
        }

        function sendOverWire(clonedFabricObject) {
            var json = JSON.stringify(clonedFabricObject);
            SocketIoService.send().addObject(json);
        }
        self.setActiveCanvasTool('None');

    };
    this.getCanvasAsBase64 = function(imagetype){
        return FabricService.canvas().toDataURL(imagetype);
    };
    this.canvasTools = function () {
        return canvasToolOptions;
    };
    this.saveCanvas = function(){
        SocketIoService.send().saveCanvas(
            {
                randomString: UserService.user().randomString,
                room: UserService.user().room,
                canvas: JSON.stringify(FabricService.canvas().toJSON(['timestamp']))
            });
    };
    function canvasToolNone() {
        FabricService.canvas().isDrawingMode = false;
        FabricService.removeMouseDown();
        FabricService.removePathCreated();
    }

    function canvasToolWrite() {
        FabricService.mouseDown(iTextMouseDown);
        function iTextMouseDown(options) {
            if (!options.target) {
                var iText = FabricService.createItext(options);
                createAndSyncFrom(iText);
                ListenerService.attachListenersToFabricObject(iText);
                iText.enterEditing();
                iText.selectionStart = 0;
                iText.selectionEnd = iText.text.length;
                self.setActiveCanvasTool('None');
                FabricService.canvas().renderAll();
            }
        }
    }

    function canvasToolRect() {
        FabricService.mouseDown(rectMouseDown);
        function rectMouseDown(options) {
            if (!options.target) {
                var rect = FabricService.createRect(options);
                createAndSyncFrom(rect);
                ListenerService.attachListenersToFabricObject(rect);
                self.setActiveCanvasTool('None');
                FabricService.canvas().renderAll();
            }
        }
    }

    function canvasToolDraw() {
        FabricService.canvas().isDrawingMode = true;
        FabricService.pathCreated(drawPath);
        function drawPath(options) {
            var fabricObject = options.path;
            fabricObject.objectId = Utils.guid();
            var fabricObjectJson = JSON.stringify(fabricObject);
            SocketIoService.send().addObject(fabricObjectJson);
            ListenerService.attachListenersToFabricObject(fabricObject)
        }
    }

    function canvasToolArrow() {
        FabricService.mouseDown(createArrow);

        function createArrow(options) {
            if (!options.target) {
                var arrow = FabricService.createArrow(options);
                createAndSyncFrom(arrow);
                ListenerService.attachListenersToFabricObject(arrow);
                self.setActiveCanvasTool('None');
                FabricService.canvas().renderAll();
            }
        }
    }

    function createAndSyncFrom(fabricObject) {
        var json = JSON.stringify(fabricObject);
        SocketIoService.send().addObject(json);
        FabricService.canvas().calcOffset();
        FabricService.canvas().add(fabricObject);
        FabricService.canvas().setActiveObject(fabricObject);
    }

    this.findActiveCanvasTool = function () {
        return canvasToolOptions.filter(function (tool) {
            if (tool.active) {
                return true;
            }
            return false;
        })[0];
    }
    this.findCanvasTool = function (name) {
        return canvasToolOptions.filter(function (tool) {
            if (tool.name === name) {
                return true;
            }
            return false;
        })[0];
    }
    this.setActiveCanvasTool = function (name) {
        var activeCanvasTool = this.findActiveCanvasTool();
        if (activeCanvasTool) {
            if (!name || activeCanvasTool.name === name) {
                return;
            }
            activeCanvasTool.active = false;
        }
        var tool = this.findCanvasTool(name);
        tool.active = true;
        tool.fn();
    }
    this.isDrawingMode = function (value) {
        FabricService.canvas().isDrawingMode = value;
    }
    this.calculateOffset = function () {
        FabricService.canvas().calcOffset();
    }

}])<|endoftext|>


<commit_before>/* Computation of an estimate of Delta T, for astronomical computations with calendars
Character set is UTF-8
Contents:
		getDeltaT : an estimate of DeltaT, defined as: UTC = TT - DeltaT. UTC is former GMT,
*/
/* Version	M2021-07-29 extracted and isolated from Lunar.js
	M2021-03-11	Update formula for average Delta D after Morrison and Stephenson 2021
*/
/* Copyright Miletus 2016-2021 - Louis A. de Fouquières
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
	1. The above copyright notice and this permission notice shall be included
	in all copies or substantial portions of the Software.
	2. Changes with respect to any former version shall be documented.

The software is provided "as is", without warranty of any kind,
express of implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose and noninfringement.
In no event shall the authors of copyright holders be liable for any
claim, damages or other liability, whether in an action of contract,
tort or otherwise, arising from, out of or in connection with the software
or the use or other dealings in the software.
Inquiries: www.calendriermilesien.org
*/
/* Requires: nothing
*/
"use strict";
	/** Compute an estimate of Delta T, defined as: UTC = TT - Delta T. The estimate is only the quadratic part of Delta T.
	 * @function getDeltaT
	 * @param {Date} the date where Delta T is estimated (estimation is per exact date, not per year)
	 * return {number} Delta T. Unit is milliseconds, result reflects an integer signed number of seconds
	*/
export default function	getDeltaT (theDate) {
		const JULIAN_CENTURY_UNIT = 36525 * 86400000,
			SECOND_UNIT = 1000, 	// used with legacy Date object
			ORIGIN = new Date (1825, 0, 1); // 1 January 1825
		let century = (theDate.getTime() - ORIGIN.getTime()) / JULIAN_CENTURY_UNIT;
		return Math.round(century*century*31.4 - 10) * SECOND_UNIT; // Precision is not less than one second
	}
<commit_msg>Recover comments<commit_after>/* Computation of an estimate of Delta T, for astronomical computations with calendars
Character set is UTF-8
Contents:
	getDeltaT : an estimate of DeltaT, defined as:
				UTC = TT - DeltaT. UTC is former GMT.
		TT is Terrestrial Time, a uniform time scale defined with a second defined independently from Earth movements.
		DeltaT is erratic and difficult to compute, however, the general trend of DeltaT is due to the braking  of the Earth's daily revolution.
		This estimate of Delta T in seconds from the year expressed in Common Era is: -20 + 32 v², where v = (A – 1820) / 100.
		In this version, Delta T is computed from a fractional value of the time. The result is rounded to the nearest second.
*/
/* Version	M2021-08-02	Recover comments describing Delta T that had been lost when splitting.
	M2021-07-29 extracted and isolated from Lunar.js
	M2021-03-11	Update formula for average Delta D after Morrison and Stephenson 2021
*/
/* Copyright Miletus 2016-2021 - Louis A. de Fouquières
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
	1. The above copyright notice and this permission notice shall be included
	in all copies or substantial portions of the Software.
	2. Changes with respect to any former version shall be documented.

The software is provided "as is", without warranty of any kind,
express of implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose and noninfringement.
In no event shall the authors of copyright holders be liable for any
claim, damages or other liability, whether in an action of contract,
tort or otherwise, arising from, out of or in connection with the software
or the use or other dealings in the software.
Inquiries: www.calendriermilesien.org
*/
/* Requires: nothing
*/
"use strict";
	/** Compute an estimate of Delta T, defined as: UTC = TT - Delta T. The estimate is only the quadratic part of Delta T.
	 * @function getDeltaT
	 * @param {Date} the date where Delta T is estimated (estimation is per exact date, not per year)
	 * return {number} Delta T. Unit is milliseconds, result reflects an integer signed number of seconds
	*/
export default function	getDeltaT (theDate) {
		const JULIAN_CENTURY_UNIT = 36525 * 86400000,
			SECOND_UNIT = 1000, 	// used with legacy Date object
			ORIGIN = new Date (1825, 0, 1); // 1 January 1825
		let century = (theDate.getTime() - ORIGIN.getTime()) / JULIAN_CENTURY_UNIT;
		return Math.round(century*century*31.4 - 10) * SECOND_UNIT; // Precision is not less than one second
	}
<|endoftext|>