<commit_before>/*jshint camelcase:false */
/*global Spinner*/

(function($) {

    var spinnerOpts = {
      lines: 13, // The number of lines to draw
      length: 6, // The length of each line
      width: 2, // The line thickness
      radius: 8, // The radius of the inner circle
      corners: 1, // Corner roundness (0..1)
      rotate: 0, // The rotation offset
      color: '#000', // #rgb or #rrggbb
      speed: 1, // Rounds per second
      trail: 60, // Afterglow percentage
      shadow: false, // Whether to render a shadow
      hwaccel: false, // Whether to use hardware acceleration
      className: 'spinner', // The CSS class to assign to the spinner
      zIndex: 2e9, // The z-index (defaults to 2000000000)
      top: 'auto', // Top position relative to parent in px
      left: 'auto' // Left position relative to parent in px
    };

    // jquery spinner plugin
    $.fn.spin = function(opts) {
      this.each(function() {
        var $this = $(this),
            data = $this.data();

        if (data.spinner) {
          data.spinner.stop();
          delete data.spinner;
        }
        if (opts !== false) {
          data.spinner = new Spinner($.extend({color: $this.css('color')}, opts)).spin(this);
        }
      });
      return this;
    };

    $(document).ready(function () {
        $("#create_course_btn").click(function() {
            $("#create_course_btn").toggleClass("btn btn-success");
            $("#create_course_btn").attr("value","Submitting...");
            $("#button-container").spin(spinnerOpts);
        });

        $('#course_list').on('click', 'input[type="checkbox"]', function() {
            enable_submit_crosslist();
			if (this.id.indexOf('sandbox') === -1) {
                cross_list_course_title();
			}
        });

		$('.new_course_container').on('click', '#cross_list', function() {
			cross_list_course_title();
        });

        $("#update_course_list").click(function() {
            var sfuid = $("#username").val();
            $("#enroll_me_div").hide();
            $("#course_list").html("
Retrieving course list...
");
            $("#course_list").spin(spinnerOpts);

            $.ajax({
              url: "/sfu/user/" + sfuid,
              dataType: "json",
              success: function(data) {
                if (data.login_id !== null && data.login_id !== undefined){
                    course_list(sfuid);
                } else {
                    $("#course_list").html("
Invalid SFU Computing ID
");
                }
              },
              error: function(xhr) {
                var statusCode = xhr.status;
                if (statusCode === 404) {
                    $("#course_list").html("
Invalid SFU Computing ID
");
                } else {
                    $("#course_list").html("
An unknown error occurred
");
                }
              }
            });
        });

       $("#username").keypress(function(ev){
        if (ev.keyCode === 10 || ev.keyCode === 13) {
          ev.preventDefault();
          $('#update_course_list').trigger('click')
        }
       });
       $("#enroll_me_div").hide();
       $("#course_list").html("
Retrieving course list...
").spin(spinnerOpts);
       course_list();
    });

    function course_list() {
        toggle_enroll_me();
        var sfuid = $("#username").val();

        $.ajax({
          url: "/sfu/terms/" + sfuid,
          dataType: "json",
          success: function(data) {
            $("#course_list").html("");

            $.each(data, function (index, term) {
                $("#course_list").append('

' + term.formatted1 + '

');
                $("#"+term.peopleSoftCode+"_courses").html(" Retrieving courses... ");
                courses_for_terms(sfuid, term.peopleSoftCode);
            });
           sandbox_course(sfuid);
          },
          error: function(xhr) {
            var statusCode = xhr.status;
            if (statusCode === 404) {
                $("#course_list").html("
Invalid SFU Computing ID
");
            } else {
                $("#course_list").html("
An unknown error occurred
");
            }
          }
        })
    }

    function courses_for_terms(sfuid, term) {
        $("#" + term + "_courses").spin(spinnerOpts);
        $.ajax({
            url: "/sfu/courses/" + sfuid + "/" + term,
            dataType: 'json',
            success: function(data) {
                var num = 1;
                $("#"+term+"_courses").html("");
                $.each(data, function (index, course) {
                    var section_tutorials = course.sectionTutorials;
                    var course_display = course.name + course.number + " - " + course.section + " " + course.title;
                    if (section_tutorials) {
                        course_display += "
 (Includes section tutorials: " + section_tutorials  + ") ";
                    }
                    var course_value = course.key;
                    var checkbox_html = '<input type="checkbox" name="selected_course_'+ num +'_'+ term +'" id="selected_course_'+ num +'_'+ term +'" value="'+ course_value + '">' + course_display +'';
                    $("#"+term+"_courses").append(checkbox_html);
                    num++;
                });
            },
            error: function() {  /* TODO: do something useful here */ }
        });
    }

    function enable_submit_crosslist() {
        var num_selected_courses = "";
        var selected_terms = [];
        $('input[type="checkbox"]:checked').each(function() {
            if ($(this).attr('id').match(/^selected_course_/)) {
                num_selected_courses++;
                var checkbox_id_arr = $(this).attr('id').split("_");
                selected_terms.push(checkbox_id_arr[checkbox_id_arr.length-1]);
            }
        }).get();

        if ( (num_selected_courses > 2) || (num_selected_courses > 1 && !$("#selected_course_sandbox").is(':checked')) ) {
            $("#create_course_btn").removeAttr("disabled");
            $("#enroll_me").removeAttr("disabled");
            enable_cross_list(true);
        } else if (num_selected_courses > 0) {
            $("#create_course_btn").removeAttr("disabled");
            $("#enroll_me").removeAttr("disabled");
            enable_cross_list(false);
        } else {
            $("#create_course_btn").attr("disabled", "disabled");
            enable_cross_list(false);
        }

        if (jQuery.unique(selected_terms).length > 1) enable_cross_list(false); // Cannot cross-list across terms
    }

    function cross_list_course_title() {
        // Disable Sandbox checkbox since it should not be cross-listed
        if ($("#cross_list").is(':checked')) {
            $("#cross-list-course").html("");
            $("#selected_course_sandbox").removeAttr("checked");
            $("#selected_course_sandbox").attr("disabled", "disabled");
            //var checked = $("input[type='checkbox']:checked");
            var cross_list_title = "";
            $('input[type="checkbox"]:checked').each(function() {
                if ($(this).attr('id').match(/^selected_course_/) && $(this).attr('id') !== "selected_course_sandbox" ) {
                    var course_info = $(this).val().split(":::");
                    cross_list_title += course_info[1].toUpperCase() + course_info[2] + " - " + course_info[3].toUpperCase() + " / ";
                }
            }).get();
            $("#cross-list-course").html("  "" + cross_list_title.slice(0,-3) + """);
            $("#create_course_btn").attr("value","Create Cross-List Course");
        } else {
            $("#selected_course_sandbox").removeAttr("disabled");
            $("#cross-list-course").html("");
            $("#create_course_btn").attr("value","Create Courses");
        }
    }

    function toggle_enroll_me(){
        if ($("#username").val() !== $("#enroll_me").val()) {
            $("#enroll_me_div").show();
        } else {
            $("#enroll_me_div").hide();
        }
    }

    function enable_cross_list(enable){
        if (enable) {
            $("#cross_list").removeAttr("disabled");
        } else {
            $("#cross_list").removeAttr("checked");
            $("#cross_list").attr("disabled", "disabled");
            $("#cross-list-course").html("");
        }
    }

    function sandbox_course(sfuid) {
        var title = "Sandbox - " + sfuid;
        $.ajax({
            url: "/sfu/sandbox/" + sfuid,
            dataType: 'json',
            success: function(data) {
                if (data.sis_source_id != "sandbox-" + sfuid + "-1:::course") {
                    $("#course_list").append("

Other

");
                    var checkbox_html = '<input type="checkbox" name="selected_course_sandbox" id="selected_course_sandbox" value="sandbox" onchange="enable_submit_crosslist();">'+ title +'';
                    $("#sandbox").append(checkbox_html);
                }
            },
            error: function() {  /* TODO: do something useful here */ }
        });
    }

})(jQuery);<commit_msg>Added functionality to accept email for username field<commit_after>/*jshint camelcase:false */
/*global Spinner*/

(function($) {

    var spinnerOpts = {
      lines: 13, // The number of lines to draw
      length: 6, // The length of each line
      width: 2, // The line thickness
      radius: 8, // The radius of the inner circle
      corners: 1, // Corner roundness (0..1)
      rotate: 0, // The rotation offset
      color: '#000', // #rgb or #rrggbb
      speed: 1, // Rounds per second
      trail: 60, // Afterglow percentage
      shadow: false, // Whether to render a shadow
      hwaccel: false, // Whether to use hardware acceleration
      className: 'spinner', // The CSS class to assign to the spinner
      zIndex: 2e9, // The z-index (defaults to 2000000000)
      top: 'auto', // Top position relative to parent in px
      left: 'auto' // Left position relative to parent in px
    };

    // jquery spinner plugin
    $.fn.spin = function(opts) {
      this.each(function() {
        var $this = $(this),
            data = $this.data();

        if (data.spinner) {
          data.spinner.stop();
          delete data.spinner;
        }
        if (opts !== false) {
          data.spinner = new Spinner($.extend({color: $this.css('color')}, opts)).spin(this);
        }
      });
      return this;
    };

    $(document).ready(function () {
        $("#create_course_btn").click(function() {
            $("#create_course_btn").toggleClass("btn btn-success");
            $("#create_course_btn").attr("value","Submitting...");
            $("#button-container").spin(spinnerOpts);
        });

        $('#course_list').on('click', 'input[type="checkbox"]', function() {
            enable_submit_crosslist();
			if (this.id.indexOf('sandbox') === -1) {
                cross_list_course_title();
			}
        });

		$('.new_course_container').on('click', '#cross_list', function() {
			cross_list_course_title();
        });

        $("#update_course_list").click(function() {
            var sfuid = username($("#username").val());
            $("#enroll_me_div").hide();
            $("#course_list").html("
Retrieving course list...
");
            $("#course_list").spin(spinnerOpts);

            $.ajax({
              url: "/sfu/user/" + sfuid,
              dataType: "json",
              success: function(data) {
                if (data.login_id !== null && data.login_id !== undefined){
                    course_list(sfuid);
                } else {
                    $("#course_list").html("
Invalid SFU Computing ID
");
                }
              },
              error: function(xhr) {
                var statusCode = xhr.status;
                if (statusCode === 404) {
                    $("#course_list").html("
Invalid SFU Computing ID
");
                } else {
                    $("#course_list").html("
An unknown error occurred
");
                }
              }
            });
        });

       $("#username").keypress(function(ev){
        if (ev.keyCode === 10 || ev.keyCode === 13) {
          ev.preventDefault();
          $('#update_course_list').trigger('click')
        }
       });
       $("#enroll_me_div").hide();
       $("#course_list").html("
Retrieving course list...
").spin(spinnerOpts);
       course_list();
    });

    function course_list() {
        toggle_enroll_me();
        var sfuid = username($("#username").val());

        $.ajax({
          url: "/sfu/terms/" + sfuid,
          dataType: "json",
          success: function(data) {
            $("#course_list").html("");

            $.each(data, function (index, term) {
                $("#course_list").append('

' + term.formatted1 + '

');
                $("#"+term.peopleSoftCode+"_courses").html(" Retrieving courses... ");
                courses_for_terms(sfuid, term.peopleSoftCode);
            });
           sandbox_course(sfuid);
          },
          error: function(xhr) {
            var statusCode = xhr.status;
            if (statusCode === 404) {
                $("#course_list").html("
Invalid SFU Computing ID
");
            } else {
                $("#course_list").html("
An unknown error occurred
");
            }
          }
        })
    }

    function courses_for_terms(sfuid, term) {
        $("#" + term + "_courses").spin(spinnerOpts);
        $.ajax({
            url: "/sfu/courses/" + sfuid + "/" + term,
            dataType: 'json',
            success: function(data) {
                var num = 1;
                $("#"+term+"_courses").html("");
                $.each(data, function (index, course) {
                    var section_tutorials = course.sectionTutorials;
                    var course_display = course.name + course.number + " - " + course.section + " " + course.title;
                    if (section_tutorials) {
                        course_display += "
 (Includes section tutorials: " + section_tutorials  + ") ";
                    }
                    var course_value = course.key;
                    var checkbox_html = '<input type="checkbox" name="selected_course_'+ num +'_'+ term +'" id="selected_course_'+ num +'_'+ term +'" value="'+ course_value + '">' + course_display +'';
                    $("#"+term+"_courses").append(checkbox_html);
                    num++;
                });
            },
            error: function() {  /* TODO: do something useful here */ }
        });
    }

    function enable_submit_crosslist() {
        var num_selected_courses = "";
        var selected_terms = [];
        $('input[type="checkbox"]:checked').each(function() {
            if ($(this).attr('id').match(/^selected_course_/)) {
                num_selected_courses++;
                var checkbox_id_arr = $(this).attr('id').split("_");
                selected_terms.push(checkbox_id_arr[checkbox_id_arr.length-1]);
            }
        }).get();

        if ( (num_selected_courses > 2) || (num_selected_courses > 1 && !$("#selected_course_sandbox").is(':checked')) ) {
            $("#create_course_btn").removeAttr("disabled");
            $("#enroll_me").removeAttr("disabled");
            enable_cross_list(true);
        } else if (num_selected_courses > 0) {
            $("#create_course_btn").removeAttr("disabled");
            $("#enroll_me").removeAttr("disabled");
            enable_cross_list(false);
        } else {
            $("#create_course_btn").attr("disabled", "disabled");
            enable_cross_list(false);
        }

        if (jQuery.unique(selected_terms).length > 1) enable_cross_list(false); // Cannot cross-list across terms
    }

    function cross_list_course_title() {
        // Disable Sandbox checkbox since it should not be cross-listed
        if ($("#cross_list").is(':checked')) {
            $("#cross-list-course").html("");
            $("#selected_course_sandbox").removeAttr("checked");
            $("#selected_course_sandbox").attr("disabled", "disabled");
            //var checked = $("input[type='checkbox']:checked");
            var cross_list_title = "";
            $('input[type="checkbox"]:checked').each(function() {
                if ($(this).attr('id').match(/^selected_course_/) && $(this).attr('id') !== "selected_course_sandbox" ) {
                    var course_info = $(this).val().split(":::");
                    cross_list_title += course_info[1].toUpperCase() + course_info[2] + " - " + course_info[3].toUpperCase() + " / ";
                }
            }).get();
            $("#cross-list-course").html("  "" + cross_list_title.slice(0,-3) + """);
            $("#create_course_btn").attr("value","Create Cross-List Course");
        } else {
            $("#selected_course_sandbox").removeAttr("disabled");
            $("#cross-list-course").html("");
            $("#create_course_btn").attr("value","Create Courses");
        }
    }

    function toggle_enroll_me(){
        if (username($("#username").val()) !== $("#enroll_me").val()) {
            $("#enroll_me_div").show();
        } else {
            $("#enroll_me_div").hide();
        }
    }

    function enable_cross_list(enable){
        if (enable) {
            $("#cross_list").removeAttr("disabled");
        } else {
            $("#cross_list").removeAttr("checked");
            $("#cross_list").attr("disabled", "disabled");
            $("#cross-list-course").html("");
        }
    }

    function sandbox_course(sfuid) {
        var title = "Sandbox - " + sfuid;
        $.ajax({
            url: "/sfu/sandbox/" + sfuid,
            dataType: 'json',
            success: function(data) {
                if (data.sis_source_id != "sandbox-" + sfuid + "-1:::course") {
                    $("#course_list").append("

Other

");
                    var checkbox_html = '<input type="checkbox" name="selected_course_sandbox" id="selected_course_sandbox" value="sandbox" onchange="enable_submit_crosslist();">'+ title +'';
                    $("#sandbox").append(checkbox_html);
                }
            },
            error: function() {  /* TODO: do something useful here */ }
        });
    }

    function username(value) {
        username = value;
        if (value.contains("@")) username = value.split("@")[0];
        $("#username").val(username);
        return username;
    }

})(jQuery);<|endoftext|>


<commit_before>NumberButton.prototype = Object.create(GeneralButton.prototype);
NumberButton.prototype.constructor = NumberButton;

/**
 * A button with number representations on it.
 * If you supply more than one representation the button will stretch.
 * Publishes numberPress event on click.
 * NOTE: This button will not go to "up" state after click unless you set keepDown option to false.
 * @param {number} number - The number for the button.
 * @param {number|Array} representations - The representations of the button (see GLOBAL.NUMBER_REPRESENTATION).
 * @param {Object} options - A list of options (in addition to GeneralButton):
 *        {number} min: The minimum value of the button.
 *        {number} max: The maximum value of the button.
 *        {number} size: the small side of the button (the other depend on representation amount) (default 75).
 *        {boolean} vertical: stretch button vertically if many representations, otherwise horisontally (default true).
 * @return {Object} Itself.
 */
function NumberButton (number, representations, options) {
	/* The order here is a bit weird because GeneralButton calls setSize, which this class overshadows. */
	if (typeof options.keepDown === 'undefined' || options.keepDown === null) {
		options.keepDown = true;
	}
	this.representations = representations;

	GeneralButton.call(this, options); // Parent constructor.

	this.vertical = options.vertical;
	if (typeof this.vertical === 'undefined' || this.vertical === null) {
		this.vertical = true;
	}
	this.setDirection(!this.vertical);

	this.min = options.min || null;
	this.max = options.max || null;
	this._number = 0;
	this.number = number;

	this._clicker = options.onClick;
	/* This will be called in the GeneralButton's onInputDown */
	this.onClick = function () {
		EventSystem.publish(GLOBAL.EVENT.numberPress, [this.number, this.representations]);
		if (this._clicker) {
			this._clicker(this.number);
		}
	};

	return this;
}

/**
 * @property {number|Array} representations - The representations on the button.
 */
Object.defineProperty(NumberButton.prototype, 'representations', {
	get: function () {
		return this._representations;
	},
	set: function (value) {
		this._representations = Array.isArray(value) ? value : [value];
		if (typeof this.number !== 'undefined' && this.number !== null) {
			this.updateGraphics();
		}
	}
});

/**
 * @property {number} number - The number on the button. Set according to representations.
 *                             NOTE: This can not be less or more than min or max.
 */
Object.defineProperty(NumberButton.prototype, 'number', {
	get: function () {
		return this._number;
	},
	set: function (value) {
		/* Chcek boundaries */
		if (this.min && value < this.min) { value = this.min; }
		if (this.max && value > this.max) { value = this.max; }
		if (value === this._number) { return; }

		this._number = value;

		this.updateGraphics();
	}
});

/**
 * Update the graphics of the button.
 */
NumberButton.prototype.updateGraphics = function () {
	/* Remove old graphics. */
	if (this.children.length > 1) {
		this.removeBetween(1, this.children.length-1, true);
	}

	if (this.representations[0] !== GLOBAL.NUMBER_REPRESENTATION.yesno) {
		if (this._number > 0) {
			this.bg.frameName = 'buttonP-0';
		} else if (this._number < 0) {
			this.bg.frameName = 'buttonM-0';
		} else {
			this.bg.frameName = 'buttonZ-0';
		}
		this.setSize();
	}

	/* Add new graphics. */
	var x = 0;
	var y = 0;
	var offset = 0;
	var useNum = Math.abs(this._number);
	for (var i = 0; i < this.representations.length; i++) {
		if (this.vertical) {
			y = this.size * i;
		} else {
			x = this.size * i;
		}

		if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.dots) {
			offset = this.calcOffset(20);
			this.add(new DotsRepresentation(useNum, x+offset.x, y+offset.y, this.size-offset.o, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.fingers) {
			offset = this.calcOffset(24);
			this.add(new FingerRepresentation(useNum, x+offset.x, y+offset.y, this.size-offset.o, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.strikes) {
			offset = this.calcOffset(12);
			this.add(new StrikeRepresentation(useNum, x+offset.x, y+offset.y, this.size-offset.o, this.color, this.max - this.min));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.numbers) {
			this.add(new NumberRepresentation(this._number, x, y, this.size/2, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.dice) {
			offset = this.calcOffset(12);
			this.add(new DiceRepresentation(useNum, x+offset.x, y+offset.y, this.size-offset.o, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.signedNumbers) {
			this.add(new SignedNumberRepresentation(this._number, x, y, this.size/2, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.yesno) {
			this._number = this._number % 2;
			this.add(new YesnoRepresentation(this._number, x, y, this.size/2, this.color));
		}
	}
};

/**
 * Calculate the different offsets for the button (needed due to arrow in button).
 * @param {Number} offset - Offset from button edge (used like: this.size/offset).
 */
NumberButton.prototype.calcOffset = function (offset) {
	var t = {};
	t.o = this.size/offset;
	if (this.vertical) {
		t.x = t.o*(this._number >= 0 ? 1 : 3.5);
		t.y = t.o*2;
	} else {
		t.x = t.o*2;
		t.y = t.o*(this._number >= 0 ? 3.5 : 1);
	}
	t.o *= 4;
	return t;
};

/**
 * Set the size of this button.
 * @param {Number} The new size.
 */
NumberButton.prototype.setSize = function (size) {
	GeneralButton.prototype.setSize.call(this, size || this.size);

	if (this.vertical) {
		this.bg.height *= this.representations.length;
	} else {
		this.bg.width *= this.representations.length;
	}
};

/**
 * Set the direction of the background button.
 * @param {Boolean} val - True = vertical, false = horizontal.
 */
NumberButton.prototype.setDirection = function (val) {
	if (val) {
		this.bg.rotation = -Math.PI/2;
		this.bg.y += this.bg.width;
		this.bg.adjusted = this.bg.width;
	} else {
		this.bg.rotation = 0;
		this.bg.y -= this.bg.adjusted || 0;
	}
};<commit_msg>Number button: Bugfix for strike representation<commit_after>NumberButton.prototype = Object.create(GeneralButton.prototype);
NumberButton.prototype.constructor = NumberButton;

/**
 * A button with number representations on it.
 * If you supply more than one representation the button will stretch.
 * Publishes numberPress event on click.
 * NOTE: This button will not go to "up" state after click unless you set keepDown option to false.
 * @param {number} number - The number for the button.
 * @param {number|Array} representations - The representations of the button (see GLOBAL.NUMBER_REPRESENTATION).
 * @param {Object} options - A list of options (in addition to GeneralButton):
 *        {number} min: The minimum value of the button.
 *        {number} max: The maximum value of the button.
 *        {number} size: the small side of the button (the other depend on representation amount) (default 75).
 *        {boolean} vertical: stretch button vertically if many representations, otherwise horisontally (default true).
 * @return {Object} Itself.
 */
function NumberButton (number, representations, options) {
	/* The order here is a bit weird because GeneralButton calls setSize, which this class overshadows. */
	if (typeof options.keepDown === 'undefined' || options.keepDown === null) {
		options.keepDown = true;
	}
	this.representations = representations;

	GeneralButton.call(this, options); // Parent constructor.

	this.vertical = options.vertical;
	if (typeof this.vertical === 'undefined' || this.vertical === null) {
		this.vertical = true;
	}
	this.setDirection(!this.vertical);

	this.min = options.min || null;
	this.max = options.max || null;
	this._number = 0;
	this.number = number;

	this._clicker = options.onClick;
	/* This will be called in the GeneralButton's onInputDown */
	this.onClick = function () {
		EventSystem.publish(GLOBAL.EVENT.numberPress, [this.number, this.representations]);
		if (this._clicker) {
			this._clicker(this.number);
		}
	};

	return this;
}

/**
 * @property {number|Array} representations - The representations on the button.
 */
Object.defineProperty(NumberButton.prototype, 'representations', {
	get: function () {
		return this._representations;
	},
	set: function (value) {
		this._representations = Array.isArray(value) ? value : [value];
		if (typeof this.number !== 'undefined' && this.number !== null) {
			this.updateGraphics();
		}
	}
});

/**
 * @property {number} number - The number on the button. Set according to representations.
 *                             NOTE: This can not be less or more than min or max.
 */
Object.defineProperty(NumberButton.prototype, 'number', {
	get: function () {
		return this._number;
	},
	set: function (value) {
		/* Chcek boundaries */
		if (this.min && value < this.min) { value = this.min; }
		if (this.max && value > this.max) { value = this.max; }
		if (value === this._number) { return; }

		this._number = value;

		this.updateGraphics();
	}
});

/**
 * Update the graphics of the button.
 */
NumberButton.prototype.updateGraphics = function () {
	/* Remove old graphics. */
	if (this.children.length > 1) {
		this.removeBetween(1, this.children.length-1, true);
	}

	if (this.representations[0] !== GLOBAL.NUMBER_REPRESENTATION.yesno) {
		if (this._number > 0) {
			this.bg.frameName = 'buttonP-0';
		} else if (this._number < 0) {
			this.bg.frameName = 'buttonM-0';
		} else {
			this.bg.frameName = 'buttonZ-0';
		}
		this.setSize();
	}

	/* Add new graphics. */
	var x = 0;
	var y = 0;
	var offset = 0;
	var useNum = Math.abs(this._number);
	for (var i = 0; i < this.representations.length; i++) {
		if (this.vertical) {
			y = this.size * i;
		} else {
			x = this.size * i;
		}

		if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.dots) {
			offset = this.calcOffset(20);
			this.add(new DotsRepresentation(useNum, x+offset.x, y+offset.y, this.size-offset.o, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.fingers) {
			offset = this.calcOffset(24);
			this.add(new FingerRepresentation(useNum, x+offset.x, y+offset.y, this.size-offset.o, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.strikes) {
			offset = this.calcOffset(12);
			this.add(new StrikeRepresentation(useNum, x+offset.x, y+offset.y, this.size-offset.o, this.color, this.max - this.min + 1));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.numbers) {
			this.add(new NumberRepresentation(this._number, x, y, this.size/2, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.dice) {
			offset = this.calcOffset(12);
			this.add(new DiceRepresentation(useNum, x+offset.x, y+offset.y, this.size-offset.o, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.signedNumbers) {
			this.add(new SignedNumberRepresentation(this._number, x, y, this.size/2, this.color));

		} else if (this.representations[i] === GLOBAL.NUMBER_REPRESENTATION.yesno) {
			this._number = this._number % 2;
			this.add(new YesnoRepresentation(this._number, x, y, this.size/2, this.color));
		}
	}
};

/**
 * Calculate the different offsets for the button (needed due to arrow in button).
 * @param {Number} offset - Offset from button edge (used like: this.size/offset).
 */
NumberButton.prototype.calcOffset = function (offset) {
	var t = {};
	t.o = this.size/offset;
	if (this.vertical) {
		t.x = t.o*(this._number >= 0 ? 1 : 3.5);
		t.y = t.o*2;
	} else {
		t.x = t.o*2;
		t.y = t.o*(this._number >= 0 ? 3.5 : 1);
	}
	t.o *= 4;
	return t;
};

/**
 * Set the size of this button.
 * @param {Number} The new size.
 */
NumberButton.prototype.setSize = function (size) {
	GeneralButton.prototype.setSize.call(this, size || this.size);

	if (this.vertical) {
		this.bg.height *= this.representations.length;
	} else {
		this.bg.width *= this.representations.length;
	}
};

/**
 * Set the direction of the background button.
 * @param {Boolean} val - True = vertical, false = horizontal.
 */
NumberButton.prototype.setDirection = function (val) {
	if (val) {
		this.bg.rotation = -Math.PI/2;
		this.bg.y += this.bg.width;
		this.bg.adjusted = this.bg.width;
	} else {
		this.bg.rotation = 0;
		this.bg.y -= this.bg.adjusted || 0;
	}
};<|endoftext|>


<commit_before><commit_msg>Insert parens for SequenceExpressions that are children of ConditionalExpressions.<commit_after><|endoftext|>


<commit_before>var head = [],
  body = [],
  bodyx = [],
  bodyy = [],
  stop = 0;

function setup() {
  createCanvas(600, 600);
  background(0);
  head.push(new Head());
  body.push(new Body());
}

function draw() {
  background(0);
  if (stop == 0) {
    for (var i = 0; i < head.length; i++) {
      head[i].display();
      head[0].reset;
      head[i].move();
      head[0].food();
    }
  }
  if (stop == 0) {
    for (var l = 0; l < body.length; l++) {
      body[l].display();
    }
  }
  textSize(20);
  fill(255);
  text("©Javi", width - 55, height - 10);
  if (stop == 1) {

  }
}

function Head() {
  this.x = 0;
  this.y = 0;
  this.len = 10;
  this.time = 0;
  this.speedX = 25;
  this.speedY = 0;
  this.foodX = random(width / 25);
  this.foodY = random(height / 25);
  this.foodX = round(this.foodX);
  this.foodY = round(this.foodY);
  if (this.foodX > width / 25 - 1) {
    this.foodX--;
  }
  if (this.foodY > height / 25 - 1) {
    this.foodY--;
  }
  this.display = function() {
    fill(255);
    rect(this.x, this.y, 25, 25);
  }

  this.food = function() {
    //display
    fill(255, 0, 0);
    rect(this.foodX * 25, this.foodY * 25, 25, 25);
    //eat
    if (this.foodX * 25 == this.x && this.foodY * 25 == this.y) {
      this.foodX = random(width / 25);
      this.foodY = random(height / 25);
      this.foodX = round(this.foodX);
      this.foodY = round(this.foodY);
      if (this.foodX > width / 25 - 1) {
        this.foodX--;
      }
      if (this.foodY > height / 25 - 1) {
        this.foodY--;
      }
      bodyx.push(this.x);
      bodyy.push(this.y);
      body.push(new Body());
      if (this.len > -1) {
        this.len = this.len - 0.15;
      }
    }
  };
  this.move = function() {
    if (keyIsDown(UP_ARROW) && this.speedY == 0) {
      this.speedX = 0;
      this.speedY = -25;
    }
    if (keyIsDown(DOWN_ARROW) && this.speedY == 0) {
      this.speedX = 0;
      this.speedY = 25;
    }
    if (keyIsDown(LEFT_ARROW) && this.speedX == 0) {
      this.speedX = -25;
      this.speedY = 0;
    }
    if (keyIsDown(RIGHT_ARROW) && this.speedX == 0) {
      this.speedX = 25;
      this.speedY = 0;
    }

    if (this.time > this.len) {
      this.x = this.x + this.speedX;
      this.y = this.y + this.speedY;
          //stop
      if (this.x > width || this.x < 0) {
        stop = 1;
      }
      if (this.y > height || this.y < 0) {
        stop = 1;
      }
      for (var c = 0; c < bodyx.length - 1; c++) {
        if (bodyx[c] == this.x && bodyy[c] == this.y) {
          stop = 1;
        }
      }
      //stop
      this.time = 0;
      bodyx.push(this.x);
      bodyy.push(this.y);
      bodyx.splice(0, 1);
      bodyy.splice(0, 1);
    }
    this.time++;
  };
}

function Body() {
  this.time = 0;
  this.display = function() {
    for (var i = 0; i < bodyx.length; i++) {
      fill(255);
      rect(bodyx[i], bodyy[i], 25, 25);
    }
  };
}
<commit_msg>Update sketch.js<commit_after>var head = [],
  body = [],
  bodyx = [],
  bodyy = [],
  stop = 0;

function setup() {
  createCanvas(600, 600);
  background(0);
  head.push(new Head());
  body.push(new Body());
}

function draw() {
  background(0);
  if (stop == 0) {
    for (var i = 0; i < head.length; i++) {
      head[i].display();
      head[0].reset;
      head[i].move();
      head[0].food();
    }
  }
  if (stop == 0) {
    for (var l = 0; l < body.length; l++) {
      body[l].display();
    }
  }
  textSize(20);
  fill(255);
  text("©Javi", width - 55, height - 10);
  if (stop == 1) {

  }
}

function Head() {
  this.x = 0;
  this.y = 0;
  this.len = 10;
  this.time = 0;
  this.speedX = 25;
  this.speedY = 0;
  this.foodX = random(width / 25);
  this.foodY = random(height / 25);
  this.foodX = round(this.foodX);
  this.foodY = round(this.foodY);
  if (this.foodX > width / 25 - 1) {
    this.foodX--;
  }
  if (this.foodY > height / 25 - 1) {
    this.foodY--;
  }
  this.display = function() {
    fill(255);
    rect(this.x, this.y, 25, 25);
  }

  this.food = function() {
    //display
    fill(255, 0, 0);
    rect(this.foodX * 25, this.foodY * 25, 25, 25);
    //eat
    if (this.foodX * 25 == this.x && this.foodY * 25 == this.y) {
      this.foodX = random(width / 25);
      this.foodY = random(height / 25);
      this.foodX = round(this.foodX);
      this.foodY = round(this.foodY);
      if (this.foodX > width / 25 - 1) {
        this.foodX--;
      }
      if (this.foodY > height / 25 - 1) {
        this.foodY--;
      }
      bodyx.push(this.x);
      bodyy.push(this.y);
      body.push(new Body());
      if (this.len > -1) {
        this.len = this.len - 0.15;
      }
    }
  };
  this.move = function() {
    if (keyIsDown(UP_ARROW) && this.speedY == 0) {
      this.speedX = 0;
      this.speedY = -25;
    }
    if (keyIsDown(DOWN_ARROW) && this.speedY == 0) {
      this.speedX = 0;
      this.speedY = 25;
    }
    if (keyIsDown(LEFT_ARROW) && this.speedX == 0) {
      this.speedX = -25;
      this.speedY = 0;
    }
    if (keyIsDown(RIGHT_ARROW) && this.speedX == 0) {
      this.speedX = 25;
      this.speedY = 0;
    }

    if (this.time > this.len) {
          //stop
      if (this.x > width || this.x < 0) {
        stop = 1;
      }
      if (this.y > height || this.y < 0) {
        stop = 1;
      }
      for (var c = 0; c < bodyx.length - 1; c++) {
        if (bodyx[c] == this.x && bodyy[c] == this.y) {
          stop = 1;
        }
      }
      //stop
      this.x = this.x + this.speedX;
      this.y = this.y + this.speedY;
      this.time = 0;
      bodyx.push(this.x);
      bodyy.push(this.y);
      bodyx.splice(0, 1);
      bodyy.splice(0, 1);
    }
    this.time++;
  };
}

function Body() {
  this.time = 0;
  this.display = function() {
    for (var i = 0; i < bodyx.length; i++) {
      fill(255);
      rect(bodyx[i], bodyy[i], 25, 25);
    }
  };
}
<|endoftext|>


<commit_before>'use strict';

describe('Module: tubular.services', () => {

    describe('Service: editor', () => {
        var filter, editor, scope;

        beforeEach(() => {
            module('tubular.services');
            module(($filterProvider) => {
                filter = jasmine.createSpy().and.returnValue('translated');
                $filterProvider.register('translate', () => filter);
            });

            inject((_tubularEditorService_, rootScope_) => {
                editor = _tubularEditorService_;
                scope = _$rootScope_.$new();
            });

            scope.label = 'Testcomponent';
            editor.setupScope(scope);
            editor.value = null;
        });

        it('should be defined', () => expect(editor).toBeDefined());

        it('should show isvalid info with required = false', () => {
            expect(scope.state.$valid()).toBe(true, 'should be false without value');
            expect(scope.state.$errors.length).toBe(0, 'should not have error message');

            scope.value = 'My component have a value';
            expect(scope.state.$valid()).toBe(true, 'should be false with value');
            expect(scope.state.$errors.length).toBe(0, 'should not have error message');
        });

        it('should show isvalid info', () => {
            scope.required = true;
            expect(scope.state.$valid()).toBe(false, 'should be false without value and required = true');
            expect(scope.state.$errors.length).not.toBeLessThan(0, 'should have error message');

            scope.value = 'My component have a value';
            expect(scope.state.$valid()).toBe(true, 'should be false with value');
            expect(scope.state.$errors.length).toBe(0, 'should not have error message');
        });

        it('should have getFormField defined', () => {
            expect(scope.getFormField).toBeDefined();
        });

        it('should have $dirty value', () => expect(scope.$dirty).toBeDefined());
    });
});<commit_msg>Typo in spec<commit_after>'use strict';

describe('Module: tubular.services', () => {

    describe('Service: editor', () => {
        var filter, editor, scope;

        beforeEach(() => {
            module('tubular.services');
            module(($filterProvider) => {
                filter = jasmine.createSpy().and.returnValue('translated');
                $filterProvider.register('translate', () => filter);
            });

            inject((_tubularEditorService_, _rootScope_) => {
                editor = _tubularEditorService_;
                scope = _$rootScope_.$new();
            });

            scope.label = 'Testcomponent';
            editor.setupScope(scope);
            editor.value = null;
        });

        it('should be defined', () => expect(editor).toBeDefined());

        it('should show isvalid info with required = false', () => {
            expect(scope.state.$valid()).toBe(true, 'should be false without value');
            expect(scope.state.$errors.length).toBe(0, 'should not have error message');

            scope.value = 'My component have a value';
            expect(scope.state.$valid()).toBe(true, 'should be false with value');
            expect(scope.state.$errors.length).toBe(0, 'should not have error message');
        });

        it('should show isvalid info', () => {
            scope.required = true;
            expect(scope.state.$valid()).toBe(false, 'should be false without value and required = true');
            expect(scope.state.$errors.length).not.toBeLessThan(0, 'should have error message');

            scope.value = 'My component have a value';
            expect(scope.state.$valid()).toBe(true, 'should be false with value');
            expect(scope.state.$errors.length).toBe(0, 'should not have error message');
        });

        it('should have getFormField defined', () => {
            expect(scope.getFormField).toBeDefined();
        });

        it('should have $dirty value', () => expect(scope.$dirty).toBeDefined());
    });
});<|endoftext|>


<commit_before><commit_msg>Replaced if/else by functional matcher<commit_after><|endoftext|>


<commit_before>'use strict';

/*
 * grunt-aws-lambda
 * https://github.com/Tim-B/grunt-aws-lambda
 *
 * Copyright (c) 2014 Tim-B
 * Licensed under the MIT license.
 */

var path = require('path');
var fs = require('fs');
var AWS = require('aws-sdk');
var Q = require('q');
var arnParser = require('./arn_parser');
var dateFacade = require('./date_facade');

var deployTask = {};

deployTask.getHandler = function (grunt) {

    return function () {

        grunt.config.requires('lambda_deploy.' + this.target + '.package');

        var options = this.options({
            profile: null,
            RoleArn: null,
            accessKeyId: null,
            secretAccessKey: null,
            credentialsJSON: null,
            region: 'us-east-1',
            timeout: null,
            memory: null,
            handler: null,
            enableVersioning: false,
            alias: null
        });

        if (options.profile !== null) {
            var credentials = new AWS.SharedIniFileCredentials({profile: options.profile});
            AWS.config.credentials = credentials;
        }

        if (options.RoleArn !== null) {
            AWS.config.credentials = new AWS.EC2MetadataCredentials({
                httpOptions: {timeout: 5000} // 5 second timeout
            });
            AWS.config.credentials = new AWS.TemporaryCredentials({
                RoleArn: options.RoleArn
            });
        }

        if (options.accessKeyId !== null && options.secretAccessKey !== null) {
            AWS.config.update({accessKeyId: options.accessKeyId, secretAccessKey: options.secretAccessKey});
        }

        if (options.credentialsJSON !== null) {
            AWS.config.loadFromPath(options.credentialsJSON);
        }

        AWS.config.update({region: options.region});

        var deploy_function = grunt.config.get('lambda_deploy.' + this.target + '.function');
        var deploy_arn = grunt.config.get('lambda_deploy.' + this.target + '.arn');
        var deploy_package = grunt.config.get('lambda_deploy.' + this.target + '.package');
        var package_version = grunt.config.get('lambda_deploy.' + this.target + '.version');
        var package_name = grunt.config.get('lambda_deploy.' + this.target + '.package_name');
        var archive_name = grunt.config.get('lambda_deploy.' + this.target + '.archive_name');

        if (deploy_arn === null && deploy_function === null) {
            grunt.fail.warn('You must specify either an arn or a function name.');
        }

        if (deploy_arn) {
            deploy_function = deploy_arn;
            var functionInfo = arnParser.parse(deploy_arn);
            if (functionInfo && functionInfo.region) {
                options.region = functionInfo.region;
            }
        }

        var done = this.async();

        var lambda = new AWS.Lambda({
            apiVersion: '2015-03-31'
        });

        var getDeploymentDescription = function () {
            var description = 'Deployed ';

            if (package_name) {
                description += 'package ' + package_name + ' ';
            }
            if (package_version) {
                description += 'version ' + package_version + ' ';
            }

            description += 'on ' + dateFacade.getHumanReadableTimestamp(new Date());

            if (archive_name) {
                description += ' from artifact ' + archive_name;
            }

            return description;
        };

        lambda.getFunction({FunctionName: deploy_function}, function (err, data) {

            if (err) {
                if (err.statusCode === 404) {
                    grunt.fail.warn('Unable to find lambda function ' + deploy_function + ', verify the lambda function name and AWS region are correct.');
                } else {
                    grunt.log.error('AWS API request failed with ' + err.statusCode + ' - ' + err);
                    grunt.fail.warn('Check your AWS credentials, region and permissions are correct.');
                }
            }

            var current = data.Configuration;
            var configParams = {};
            var version = '$LATEST';

            if (options.timeout !== null) {
                configParams.Timeout = options.timeout;
            }

            if (options.memory !== null) {
                configParams.MemorySize = options.memory;
            }

            if (options.handler !== null) {
                configParams.Handler = options.handler;
            }

            var updateConfig = function (func_name, func_options) {
                var deferred = Q.defer();
                if (Object.keys(func_options).length > 0) {
                    func_options.FunctionName = func_name;
                    lambda.updateFunctionConfiguration(func_options, function (err, data) {
                        if (err) {
                            grunt.fail.warn('Could not update config, check that values and permissions are valid');
                            deferred.reject();
                        } else {
                            grunt.log.writeln('Config updated.');
                            deferred.resolve();
                        }
                    });
                } else {
                    grunt.log.writeln('No config updates to make.');
                    deferred.resolve();
                }
                return deferred.promise;
            };

            var createVersion = function (func_name) {
                var deferred = Q.defer();
                if (options.enableVersioning) {
                    lambda.publishVersion({FunctionName: func_name, Description: getDeploymentDescription()}, function (err, data) {
                        if (err) {
                            grunt.fail.warn('Publishing version for function ' + func_name + ' failed with message ' + err.message);
                            deferred.reject();
                        } else {
                            version = data.Version;
                            grunt.log.writeln('Version ' + version + ' published.');
                            deferred.resolve();
                        }
                    });
                } else {
                    deferred.resolve();
                }

                return deferred.promise;
            };

            var createOrUpdateAlias = function (func_name) {
                var deferred = Q.defer();

                var params = {
                    FunctionName: func_name,
                    Name: options.alias
                };

                if (options.alias) {
                    lambda.getAlias(params, function (err, data) {
                        params.FunctionVersion = version;
                        params.Description = getDeploymentDescription();
                        var aliasFunction = 'updateAlias';
                        if (err) {
                            if (err.statusCode === 404) {
                                aliasFunction = 'createAlias';
                            } else {
                                grunt.fail.warn('Listing aliases for ' + func_name + ' failed with message ' + err.message);
                                deferred.reject();
                                return;
                            }
                        }
                        lambda[aliasFunction](params, function (err, data) {
                            if (err) {
                                grunt.fail.warn(aliasFunction + ' for ' + func_name + ' failed with message ' + err.message);
                                deferred.reject();
                            } else {
                                grunt.log.writeln('Alias ' + options.alias + ' updated.');
                                deferred.resolve();
                            }
                        });
                    });
                } else {
                    deferred.resolve();
                }

                return deferred.promise;
            };

            grunt.log.writeln('Uploading...');
            fs.readFile(deploy_package, function (err, data) {
                if (err) {
                    grunt.fail.warn('Could not read package file (' + deploy_package + '), verify the lambda package ' +
                        'location is correct, and that you have already created the package using lambda_package.');
                }

                var codeParams = {
                    FunctionName: deploy_function,
                    ZipFile: data
                };

                lambda.updateFunctionCode(codeParams, function (err, data) {
                    if (err) {
                        grunt.fail.warn('Package upload failed, check you have lambda:UpdateFunctionCode permissions.');
                    }

                    grunt.log.writeln('Package deployed.');

                    updateConfig(deploy_function, configParams)
                        .then(function () {return createVersion(deploy_function);})
                        .then(function () {return createOrUpdateAlias(deploy_function);})
                        .then(function () {
                            done(true);
                        }).catch(function (err) {
                            grunt.fail.warn('Uncaught exception: ' + err.message);
                        });
                });
            });
        });
    };
};

module.exports = deployTask;<commit_msg>Adding additional detail to package upload error message<commit_after>'use strict';

/*
 * grunt-aws-lambda
 * https://github.com/Tim-B/grunt-aws-lambda
 *
 * Copyright (c) 2014 Tim-B
 * Licensed under the MIT license.
 */

var path = require('path');
var fs = require('fs');
var AWS = require('aws-sdk');
var Q = require('q');
var arnParser = require('./arn_parser');
var dateFacade = require('./date_facade');

var deployTask = {};

deployTask.getHandler = function (grunt) {

    return function () {

        grunt.config.requires('lambda_deploy.' + this.target + '.package');

        var options = this.options({
            profile: null,
            RoleArn: null,
            accessKeyId: null,
            secretAccessKey: null,
            credentialsJSON: null,
            region: 'us-east-1',
            timeout: null,
            memory: null,
            handler: null,
            enableVersioning: false,
            alias: null
        });

        if (options.profile !== null) {
            var credentials = new AWS.SharedIniFileCredentials({profile: options.profile});
            AWS.config.credentials = credentials;
        }

        if (options.RoleArn !== null) {
            AWS.config.credentials = new AWS.EC2MetadataCredentials({
                httpOptions: {timeout: 5000} // 5 second timeout
            });
            AWS.config.credentials = new AWS.TemporaryCredentials({
                RoleArn: options.RoleArn
            });
        }

        if (options.accessKeyId !== null && options.secretAccessKey !== null) {
            AWS.config.update({accessKeyId: options.accessKeyId, secretAccessKey: options.secretAccessKey});
        }

        if (options.credentialsJSON !== null) {
            AWS.config.loadFromPath(options.credentialsJSON);
        }

        AWS.config.update({region: options.region});

        var deploy_function = grunt.config.get('lambda_deploy.' + this.target + '.function');
        var deploy_arn = grunt.config.get('lambda_deploy.' + this.target + '.arn');
        var deploy_package = grunt.config.get('lambda_deploy.' + this.target + '.package');
        var package_version = grunt.config.get('lambda_deploy.' + this.target + '.version');
        var package_name = grunt.config.get('lambda_deploy.' + this.target + '.package_name');
        var archive_name = grunt.config.get('lambda_deploy.' + this.target + '.archive_name');

        if (deploy_arn === null && deploy_function === null) {
            grunt.fail.warn('You must specify either an arn or a function name.');
        }

        if (deploy_arn) {
            deploy_function = deploy_arn;
            var functionInfo = arnParser.parse(deploy_arn);
            if (functionInfo && functionInfo.region) {
                options.region = functionInfo.region;
            }
        }

        var done = this.async();

        var lambda = new AWS.Lambda({
            apiVersion: '2015-03-31'
        });

        var getDeploymentDescription = function () {
            var description = 'Deployed ';

            if (package_name) {
                description += 'package ' + package_name + ' ';
            }
            if (package_version) {
                description += 'version ' + package_version + ' ';
            }

            description += 'on ' + dateFacade.getHumanReadableTimestamp(new Date());

            if (archive_name) {
                description += ' from artifact ' + archive_name;
            }

            return description;
        };

        lambda.getFunction({FunctionName: deploy_function}, function (err, data) {

            if (err) {
                if (err.statusCode === 404) {
                    grunt.fail.warn('Unable to find lambda function ' + deploy_function + ', verify the lambda function name and AWS region are correct.');
                } else {
                    grunt.log.error('AWS API request failed with ' + err.statusCode + ' - ' + err);
                    grunt.fail.warn('Check your AWS credentials, region and permissions are correct.');
                }
            }

            var current = data.Configuration;
            var configParams = {};
            var version = '$LATEST';

            if (options.timeout !== null) {
                configParams.Timeout = options.timeout;
            }

            if (options.memory !== null) {
                configParams.MemorySize = options.memory;
            }

            if (options.handler !== null) {
                configParams.Handler = options.handler;
            }

            var updateConfig = function (func_name, func_options) {
                var deferred = Q.defer();
                if (Object.keys(func_options).length > 0) {
                    func_options.FunctionName = func_name;
                    lambda.updateFunctionConfiguration(func_options, function (err, data) {
                        if (err) {
                            grunt.fail.warn('Could not update config, check that values and permissions are valid');
                            deferred.reject();
                        } else {
                            grunt.log.writeln('Config updated.');
                            deferred.resolve();
                        }
                    });
                } else {
                    grunt.log.writeln('No config updates to make.');
                    deferred.resolve();
                }
                return deferred.promise;
            };

            var createVersion = function (func_name) {
                var deferred = Q.defer();
                if (options.enableVersioning) {
                    lambda.publishVersion({FunctionName: func_name, Description: getDeploymentDescription()}, function (err, data) {
                        if (err) {
                            grunt.fail.warn('Publishing version for function ' + func_name + ' failed with message ' + err.message);
                            deferred.reject();
                        } else {
                            version = data.Version;
                            grunt.log.writeln('Version ' + version + ' published.');
                            deferred.resolve();
                        }
                    });
                } else {
                    deferred.resolve();
                }

                return deferred.promise;
            };

            var createOrUpdateAlias = function (func_name) {
                var deferred = Q.defer();

                var params = {
                    FunctionName: func_name,
                    Name: options.alias
                };

                if (options.alias) {
                    lambda.getAlias(params, function (err, data) {
                        params.FunctionVersion = version;
                        params.Description = getDeploymentDescription();
                        var aliasFunction = 'updateAlias';
                        if (err) {
                            if (err.statusCode === 404) {
                                aliasFunction = 'createAlias';
                            } else {
                                grunt.fail.warn('Listing aliases for ' + func_name + ' failed with message ' + err.message);
                                deferred.reject();
                                return;
                            }
                        }
                        lambda[aliasFunction](params, function (err, data) {
                            if (err) {
                                grunt.fail.warn(aliasFunction + ' for ' + func_name + ' failed with message ' + err.message);
                                deferred.reject();
                            } else {
                                grunt.log.writeln('Alias ' + options.alias + ' updated.');
                                deferred.resolve();
                            }
                        });
                    });
                } else {
                    deferred.resolve();
                }

                return deferred.promise;
            };

            grunt.log.writeln('Uploading...');
            fs.readFile(deploy_package, function (err, data) {
                if (err) {
                    grunt.fail.warn('Could not read package file (' + deploy_package + '), verify the lambda package ' +
                        'location is correct, and that you have already created the package using lambda_package.');
                }

                var codeParams = {
                    FunctionName: deploy_function,
                    ZipFile: data
                };

                lambda.updateFunctionCode(codeParams, function (err, data) {
                    if (err) {
                        grunt.fail.warn('Package upload failed, check you have lambda:UpdateFunctionCode permissions and that your package is not too big to upload.');
                    }

                    grunt.log.writeln('Package deployed.');

                    updateConfig(deploy_function, configParams)
                        .then(function () {return createVersion(deploy_function);})
                        .then(function () {return createOrUpdateAlias(deploy_function);})
                        .then(function () {
                            done(true);
                        }).catch(function (err) {
                            grunt.fail.warn('Uncaught exception: ' + err.message);
                        });
                });
            });
        });
    };
};

module.exports = deployTask;<|endoftext|>


<commit_before>#!/usr/bin/env node
var XLSX = require('xlsx')
var mongoose = require('mongoose')
mongoose.Promise = require('bluebird')
var Expense = require('../models/expense')
var Company = require('../models/company')
// connect to Mongo when the app initializes
mongoose.connect('mongodb://localhost/local')

function parseToJSON(fileName) {
  var lines = []

  var workbook = XLSX.readFile('FinanceSheet.xlsx')
  var sheetName = 'FinanceSheet2016'
  var worksheet = workbook.Sheets[sheetName]

  // VALUES
  var startRow = 3
  var stopRow = 591
  var dateCol = 'B'
  var detailsCol = 'C'
  var companyCol = 'D'
  var monOutCol = 'E'
  var monInCol = 'F'
  var vatInCol = 'G'
  var vatOutCol = 'H'
  var vatTotalCol = 'I'
  var totalCol = 'J'

  /* Get the value */
  for (var i = startRow; i <= stopRow; i++) {
    var date = makeDate(worksheet[dateCol + i].w)
    var details = worksheet[detailsCol + i].w
    var company = worksheet[companyCol + i].w
    var monOut = processNum(worksheet[monOutCol + i])
    var monIn = processNum(worksheet[monInCol + i])
    var vatIn = processNum(worksheet[vatInCol + i])
    var vatOut = processNum(worksheet[vatOutCol + i])
    var vatTotal = processNum(worksheet[vatTotalCol + i])
    var total = roundNumber(worksheet[totalCol + i].v)

    var line = {
      date: date,
      details: details,
      company: company,
      monOut: monOut,
      monIn: monIn,
      vatIn: vatIn,
      vatOut: vatOut,
      vatTotal: vatTotal,
      total: total
    }

    lines.push(line)
  }
  return lines
}

function processNum(cell) {
  if (typeof cell === 'undefined') {
    return 0
  }
  return roundNumber(cell.w)
}

function roundNumber(value) {
  return Math.round(value * 100) / 100
}

function makeDate(value) {
  var dateParts = value.split("/")
  return new Date(parseInt('20' + dateParts[2], 10),
    parseInt(dateParts[1], 10) - 1,
    parseInt(dateParts[0], 10))
}
function sortTransactions(json) {
  var sortedTXs = {}
  var expenses = []
  var invoices = []

  for (var line of json) {
    if (line.monOut !== 0) {
      expenses.push(line)
    } else {
      invoices.push(line)
    }
  }

  sortedTXs.expenses = expenses
  sortedTXs.invoices = invoices

  return sortedTXs
}

function findOrCreateCompany(line) {
  var companyName = line.company
  Company.findOne({ name: companyName }, function (err, doc) {
    if (doc === null) {
      new Company({ name: companyName }).save(function (err, doc) {
        saveExpenseAgainstCompany(doc._id, line)
      })
    } else {
      saveExpenseAgainstCompany(doc._id, line)
    }
  })
}

function saveExpenseAgainstCompany(companyID, line) {
  var expense = new Expense({
      company: companyID,
      items: [{ desc: line.details, total: line.monOut }]
    })

    expense.save(function (err, doc) {
      if (err == null){
        console.log('Expense Saved!')
      } else{
        console.log('Expense Error in Saving:', err)
      }
    })
}

function putExpinDB(expenses) {
  for (var line of expenses) {
    findOrCreateCompany(line)
  }
}

var json = parseToJSON()
var sortedTX = sortTransactions(json)
putExpinDB(sortedTX.expenses)<commit_msg>chmod x to excel script<commit_after>#!/usr/bin/env node
var XLSX = require('xlsx')
var mongoose = require('mongoose')
mongoose.Promise = require('bluebird')
var Expense = require('../models/expense')
var Company = require('../models/company')
// connect to Mongo when the app initializes
mongoose.connect('mongodb://localhost/local')

function parseToJSON(fileName) {
  var lines = []

  var workbook = XLSX.readFile('FinanceSheet.xlsx')
  var sheetName = 'FinanceSheet2016'
  var worksheet = workbook.Sheets[sheetName]

  // VALUES
  var startRow = 3
  var stopRow = 591
  var dateCol = 'B'
  var detailsCol = 'C'
  var companyCol = 'D'
  var monOutCol = 'E'
  var monInCol = 'F'
  var vatInCol = 'G'
  var vatOutCol = 'H'
  var vatTotalCol = 'I'
  var totalCol = 'J'

  /* Get the value */
  for (var i = startRow; i <= stopRow; i++) {
    var date = makeDate(worksheet[dateCol + i].w)
    var details = worksheet[detailsCol + i].w
    var company = worksheet[companyCol + i].w
    var monOut = processNum(worksheet[monOutCol + i])
    var monIn = processNum(worksheet[monInCol + i])
    var vatIn = processNum(worksheet[vatInCol + i])
    var vatOut = processNum(worksheet[vatOutCol + i])
    var vatTotal = processNum(worksheet[vatTotalCol + i])
    var total = roundNumber(worksheet[totalCol + i].v)

    var line = {
      date: date,
      details: details,
      company: company,
      monOut: monOut,
      monIn: monIn,
      vatIn: vatIn,
      vatOut: vatOut,
      vatTotal: vatTotal,
      total: total
    }

    lines.push(line)
  }
  return lines
}

function processNum(cell) {
  if (typeof cell === 'undefined') {
    return 0
  }
  return roundNumber(cell.w)
}

function roundNumber(value) {
  return Math.round(value * 100) / 100
}

function makeDate(value) {
  var dateParts = value.split("/")
  return new Date(parseInt('20' + dateParts[2], 10),
    parseInt(dateParts[1], 10) - 1,
    parseInt(dateParts[0], 10))
}
function sortTransactions(json) {
  var sortedTXs = {}
  var expenses = []
  var invoices = []

  for (var line of json) {
    if (line.monOut !== 0) {
      expenses.push(line)
    } else {
      invoices.push(line)
    }
  }

  sortedTXs.expenses = expenses
  sortedTXs.invoices = invoices

  return sortedTXs
}

function findOrCreateCompany(line) {
  var companyName = line.company
  Company.findOne({ name: companyName }, function (err, doc) {
    if (doc === null) {
      new Company({ name: companyName }).save(function (err, doc) {
        saveExpenseAgainstCompany(doc._id, line)
      })
    } else {
      saveExpenseAgainstCompany(doc._id, line)
    }
  })
}

function saveExpenseAgainstCompany(companyID, line) {
  var expense = new Expense({
      company: companyID,
      items: [{ desc: line.details, total: line.monOut }]
    })

    expense.save(function (err, doc) {
      if (err == null){
        console.log('Expense Saved!')
      } else{
        console.log('Expense Error in Saving:', err)
      }
    })
}

function putExpinDB(expenses) {
  for (var line of expenses) {
    findOrCreateCompany(line)
  }
}

var json = parseToJSON()
var sortedTX = sortTransactions(json)
putExpinDB(sortedTX.expenses)<|endoftext|>


<commit_before>/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */

'use strict';

/**
 * The Type2 reader code below is only used for debugging purpose since Type2
 * is only a CharString format and is never used directly as a Font file.
 *
 * So the code here is useful for dumping the data content of a .cff file in
 * order to investigate the similarity between a Type1 CharString and a Type2
 * CharString or to understand the structure of the CFF format.
 */

/**
 * Build a charset by assigning the glyph name and the human readable form
 * of the glyph data.
 */
function readCharset(aStream, aCharstrings) {
  var charset = {};

  var format = aStream.getByte();
  if (format == 0) {
    charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);

    var count = aCharstrings.length - 1;
    for (var i = 1; i < count + 1; i++) {
      var sid = aStream.getByte() << 8 | aStream.getByte();
      charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
      //log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
    }
  } else if (format == 1) {
    error('Charset Range are not supported');
  } else {
    error('Invalid charset format');
  }

  return charset;
}

/**
 * Take a Type2 binary charstring as input and transform it to a human
 * readable representation as specified by the 'The Type 2 Charstring Format',
 * chapter 3.1.
 */
function readCharstringEncoding(aString) {
  var charstringTokens = [];

  var count = aString.length;
  for (var i = 0; i < count; ) {
    var value = aString[i++];
    var token = null;

    if (value < 0) {
      continue;
    } else if (value <= 11) {
      token = CFFEncodingMap[value];
    } else if (value == 12) {
      token = CFFEncodingMap[value][aString[i++]];
    } else if (value <= 18) {
      token = CFFEncodingMap[value];
    } else if (value <= 20) {
      var mask = aString[i++];
      token = CFFEncodingMap[value];
    } else if (value <= 27) {
      token = CFFEncodingMap[value];
    } else if (value == 28) {
      token = aString[i++] << 8 | aString[i++];
    } else if (value <= 31) {
      token = CFFEncodingMap[value];
    } else if (value < 247) {
      token = parseInt(value) - 139;
    } else if (value < 251) {
      token = ((value - 247) * 256) + aString[i++] + 108;
    } else if (value < 255) {
      token = -((value - 251) * 256) - aString[i++] - 108;
    } else {// value == 255
      token = aString[i++] << 24 | aString[i++] << 16 |
              aString[i++] << 8 | aString[i];
    }

    charstringTokens.push(token);
  }

  return charstringTokens;
}

/**
 * Take a binary DICT Data as input and transform it into a human readable
 * form as specified by 'The Compact Font Format Specification', chapter 5.
 */
function readFontDictData(aString, aMap) {
  var fontDictDataTokens = [];

  var count = aString.length;
  for (var i = 0; i < count; i) {
    var value = aString[i++];
    var token = null;

    if (value == 12) {
      token = aMap[value][aString[i++]];
    } else if (value == 28) {
      token = aString[i++] << 8 | aString[i++];
    } else if (value == 29) {
      token = aString[i++] << 24 |
              aString[i++] << 16 |
              aString[i++] << 8 |
              aString[i++];
    } else if (value == 30) {
      token = '';
      var parsed = false;
      while (!parsed) {
        var byte = aString[i++];

        var nibbles = [parseInt(byte / 16), parseInt(byte % 16)];
        for (var j = 0; j < nibbles.length; j++) {
          var nibble = nibbles[j];
          switch (nibble) {
            case 0xA:
              token += '.';
              break;
            case 0xB:
              token += 'E';
              break;
            case 0xC:
              token += 'E-';
              break;
            case 0xD:
              break;
            case 0xE:
              token += '-';
              break;
            case 0xF:
              parsed = true;
              break;
            default:
              token += nibble;
              break;
          }
        }
      }
      token = parseFloat(token);
    } else if (value <= 31) {
      token = aMap[value];
    } else if (value <= 246) {
      token = parseInt(value) - 139;
    } else if (value <= 250) {
      token = ((value - 247) * 256) + aString[i++] + 108;
    } else if (value <= 254) {
      token = -((value - 251) * 256) - aString[i++] - 108;
    } else if (value == 255) {
      error('255 is not a valid DICT command');
    }

    fontDictDataTokens.push(token);
  }

  return fontDictDataTokens;
}

/**
 * Take a stream as input and return an array of objects.
 * In CFF an INDEX is a structure with the following format:
 *  {
 *    count: 2 bytes (Number of objects stored in INDEX),
 *    offsize: 1 byte (Offset array element size),
 *    offset: [count + 1] bytes (Offsets array),
 *    data: - (Objects data)
 *  }
 *
 *  More explanation are given in the 'CFF Font Format Specification',
 *  chapter 5.
 */
function readFontIndexData(aStream, aIsByte) {
  var count = aStream.getByte() << 8 | aStream.getByte();
  var offsize = aStream.getByte();

  function getNextOffset() {
    switch (offsize) {
      case 0:
        return 0;
      case 1:
        return aStream.getByte();
      case 2:
        return aStream.getByte() << 8 | aStream.getByte();
      case 3:
        return aStream.getByte() << 16 | aStream.getByte() << 8 |
               aStream.getByte();
      case 4:
      return aStream.getByte() << 24 | aStream.getByte() << 16 |
             aStream.getByte() << 8 | aStream.getByte();
    }
    error(offsize + ' is not a valid offset size');
    return null;
  };

  var offsets = [];
  for (var i = 0; i < count + 1; i++)
    offsets.push(getNextOffset());

  log('Found ' + count + ' objects at offsets :' +
      offsets + ' (offsize: ' + offsize + ')');

  // Now extract the objects
  var relativeOffset = aStream.pos;
  var objects = [];
  for (var i = 0; i < count; i++) {
    var offset = offsets[i];
    aStream.pos = relativeOffset + offset - 1;

    var data = [];
    var length = offsets[i + 1] - 1;
    for (var j = offset - 1; j < length; j++)
      data.push(aIsByte ? aStream.getByte() : aStream.getChar());
    objects.push(data);
  }

  return objects;
}

var Type2Parser = function(aFilePath) {
  var font = new Dict();

  var xhr = new XMLHttpRequest();
  xhr.open('GET', aFilePath, false);
  xhr.mozResponseType = xhr.responseType = 'arraybuffer';
  xhr.expected = (document.URL.indexOf('file:') == 0) ? 0 : 200;
  xhr.send(null);
  this.data = new Stream(xhr.mozResponseArrayBuffer || xhr.mozResponse ||
                         xhr.responseArrayBuffer || xhr.response);

  // Turn on this flag for additional debugging logs
  var debug = false;

  function dump(aStr) {
    if (debug)
      log(aStr);
  };

  function parseAsToken(aString, aMap) {
    var decoded = readFontDictData(aString, aMap);

    var stack = [];
    var count = decoded.length;
    for (var i = 0; i < count; i++) {
      var token = decoded[i];
      if (IsNum(token)) {
        stack.push(token);
      } else {
        switch (token.operand) {
          case 'SID':
            font.set(token.name, CFFStrings[stack.pop()]);
            break;
          case 'number number':
            font.set(token.name, {
              offset: stack.pop(),
              size: stack.pop()
            });
            break;
          case 'boolean':
            font.set(token.name, stack.pop());
            break;
          case 'delta':
            font.set(token.name, stack.pop());
            break;
          default:
            if (token.operand && token.operand.length) {
              var array = [];
              for (var j = 0; j < token.operand.length; j++)
                array.push(stack.pop());
              font.set(token.name, array);
            } else {
              font.set(token.name, stack.pop());
            }
            break;
        }
      }
    }
  };

  this.parse = function(aStream) {
    font.set('major', aStream.getByte());
    font.set('minor', aStream.getByte());
    font.set('hdrSize', aStream.getByte());
    font.set('offsize', aStream.getByte());

    // Move the cursor after the header
    aStream.skip(font.get('hdrSize') - aStream.pos);

    // Read the NAME Index
    dump('Reading Index: Names');
    font.set('Names', readFontIndexData(aStream));
    log('Names: ' + font.get('Names'));

    // Read the Top Dict Index
    dump('Reading Index: TopDict');
    var topDict = readFontIndexData(aStream, true);
    log('TopDict: ' + topDict);

    // Read the String Index
    dump('Reading Index: Strings');
    var strings = readFontIndexData(aStream);
    log('strings: ' + strings);

    // Fill up the Strings dictionary with the new unique strings
    for (var i = 0; i < strings.length; i++)
      CFFStrings.push(strings[i].join(''));

    // Parse the TopDict operator
    var objects = [];
    var count = topDict.length;
    for (var i = 0; i < count; i++)
      parseAsToken(topDict[i], CFFDictDataMap);

    // Read the Global Subr Index that comes just after the Strings Index
    // (cf. "The Compact Font Format Specification" Chapter 16)
    dump('Reading Global Subr Index');
    var subrs = readFontIndexData(aStream, true);
    dump(subrs);

    // Reading Private Dict
    var priv = font.get('Private');
    log('Reading Private Dict (offset: ' + priv.offset +
        ' size: ' + priv.size + ')');
    aStream.pos = priv.offset;

    var privateDict = [];
    for (var i = 0; i < priv.size; i++)
      privateDict.push(aStream.getByte());
    dump('private:' + privateDict);
    parseAsToken(privateDict, CFFDictPrivateDataMap);

    for (var p in font.map)
      dump(p + '::' + font.get(p));

    // Read CharStrings Index
    var charStringsOffset = font.get('CharStrings');
    dump('Read CharStrings Index (offset: ' + charStringsOffset + ')');
    aStream.pos = charStringsOffset;
    var charStrings = readFontIndexData(aStream, true);

    // Read Charset
    dump('Read Charset for ' + charStrings.length + ' glyphs');
    var charsetEntry = font.get('charset');
    if (charsetEntry == 0) {
      error('Need to support CFFISOAdobeCharset');
    } else if (charsetEntry == 1) {
      error('Need to support CFFExpert');
    } else if (charsetEntry == 2) {
      error('Need to support CFFExpertSubsetCharset');
    } else {
      aStream.pos = charsetEntry;
      var charset = readCharset(aStream, charStrings);
    }
  }
};

/*
 * To try the Type2 decoder on a local file in the current directory:
 *
 *  var cff = new Type2Parser("file.cff");
 *  cff.parse(this.data);
 *
 * To try the Type2 decoder on a custom built CFF array:
 *
 *  var file = new Uint8Array(cffFileArray, 0, cffFileSize);
 *  var parser = new Type2Parser();
 *  parser.parse(new Stream(file));
 *
 */

/**
 * Write to a file to the disk (works only on Firefox in privilege mode)
 * but this is useful for dumping a font file to the disk and check with
 * fontforge or the ots program what's wrong with the file.
 *
 * writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".cff");
 */
function writeToFile(aBytes, aFilePath) {
  if (!('netscape' in window))
    return;

  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
  var Cc = Components.classes,
      Ci = Components.interfaces;
  var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
  file.initWithPath(aFilePath);

  var stream = Cc['@mozilla.org/network/file-output-stream;1']
                 .createInstance(Ci.nsIFileOutputStream);
  stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0);

  var bos = Cc['@mozilla.org/binaryoutputstream;1']
              .createInstance(Ci.nsIBinaryOutputStream);
  bos.setOutputStream(stream);
  bos.writeByteArray(aBytes, aBytes.length);
  stream.close();
}

<commit_msg>cleanup<commit_after>/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */

'use strict';

/**
 * The Type2 reader code below is only used for debugging purpose since Type2
 * is only a CharString format and is never used directly as a Font file.
 *
 * So the code here is useful for dumping the data content of a .cff file in
 * order to investigate the similarity between a Type1 CharString and a Type2
 * CharString or to understand the structure of the CFF format.
 */

/**
 * Build a charset by assigning the glyph name and the human readable form
 * of the glyph data.
 */
function readCharset(aStream, aCharstrings) {
  var charset = {};

  var format = aStream.getByte();
  if (format == 0) {
    charset['.notdef'] = readCharstringEncoding(aCharstrings[0]);

    var count = aCharstrings.length - 1;
    for (var i = 1; i < count + 1; i++) {
      var sid = aStream.getByte() << 8 | aStream.getByte();
      charset[CFFStrings[sid]] = readCharstringEncoding(aCharstrings[i]);
      //log(CFFStrings[sid] + "::" + charset[CFFStrings[sid]]);
    }
  } else if (format == 1) {
    error('Charset Range are not supported');
  } else {
    error('Invalid charset format');
  }

  return charset;
}

/**
 * Take a Type2 binary charstring as input and transform it to a human
 * readable representation as specified by the 'The Type 2 Charstring Format',
 * chapter 3.1.
 */
function readCharstringEncoding(aString) {
  var charstringTokens = [];

  var count = aString.length;
  for (var i = 0; i < count; ) {
    var value = aString[i++];
    var token = null;

    if (value < 0) {
      continue;
    } else if (value <= 11) {
      token = CFFEncodingMap[value];
    } else if (value == 12) {
      token = CFFEncodingMap[value][aString[i++]];
    } else if (value <= 18) {
      token = CFFEncodingMap[value];
    } else if (value <= 20) {
      var mask = aString[i++];
      token = CFFEncodingMap[value];
    } else if (value <= 27) {
      token = CFFEncodingMap[value];
    } else if (value == 28) {
      token = aString[i++] << 8 | aString[i++];
    } else if (value <= 31) {
      token = CFFEncodingMap[value];
    } else if (value < 247) {
      token = parseInt(value) - 139;
    } else if (value < 251) {
      token = ((value - 247) * 256) + aString[i++] + 108;
    } else if (value < 255) {
      token = -((value - 251) * 256) - aString[i++] - 108;
    } else {// value == 255
      token = aString[i++] << 24 | aString[i++] << 16 |
              aString[i++] << 8 | aString[i];
    }

    charstringTokens.push(token);
  }

  return charstringTokens;
}

/**
 * Take a binary DICT Data as input and transform it into a human readable
 * form as specified by 'The Compact Font Format Specification', chapter 5.
 */
function readFontDictData(aString, aMap) {
  var fontDictDataTokens = [];

  var count = aString.length;
  for (var i = 0; i < count; i) {
    var value = aString[i++];
    var token = null;

    if (value == 12) {
      token = aMap[value][aString[i++]];
    } else if (value == 28) {
      token = aString[i++] << 8 | aString[i++];
    } else if (value == 29) {
      token = aString[i++] << 24 |
              aString[i++] << 16 |
              aString[i++] << 8 |
              aString[i++];
    } else if (value == 30) {
      token = '';
      var parsed = false;
      while (!parsed) {
        var byte = aString[i++];

        var nibbles = [parseInt(byte / 16), parseInt(byte % 16)];
        for (var j = 0; j < nibbles.length; j++) {
          var nibble = nibbles[j];
          switch (nibble) {
            case 0xA:
              token += '.';
              break;
            case 0xB:
              token += 'E';
              break;
            case 0xC:
              token += 'E-';
              break;
            case 0xD:
              break;
            case 0xE:
              token += '-';
              break;
            case 0xF:
              parsed = true;
              break;
            default:
              token += nibble;
              break;
          }
        }
      }
      token = parseFloat(token);
    } else if (value <= 31) {
      token = aMap[value];
    } else if (value <= 246) {
      token = parseInt(value) - 139;
    } else if (value <= 250) {
      token = ((value - 247) * 256) + aString[i++] + 108;
    } else if (value <= 254) {
      token = -((value - 251) * 256) - aString[i++] - 108;
    } else if (value == 255) {
      error('255 is not a valid DICT command');
    }

    fontDictDataTokens.push(token);
  }

  return fontDictDataTokens;
}

/**
 * Take a stream as input and return an array of objects.
 * In CFF an INDEX is a structure with the following format:
 *  {
 *    count: 2 bytes (Number of objects stored in INDEX),
 *    offsize: 1 byte (Offset array element size),
 *    offset: [count + 1] bytes (Offsets array),
 *    data: - (Objects data)
 *  }
 *
 *  More explanation are given in the 'CFF Font Format Specification',
 *  chapter 5.
 */
function readFontIndexData(aStream, aIsByte) {
  var count = aStream.getByte() << 8 | aStream.getByte();
  var offsize = aStream.getByte();

  function getNextOffset() {
    switch (offsize) {
      case 0:
        return 0;
      case 1:
        return aStream.getByte();
      case 2:
        return aStream.getByte() << 8 | aStream.getByte();
      case 3:
        return aStream.getByte() << 16 | aStream.getByte() << 8 |
               aStream.getByte();
      case 4:
      return aStream.getByte() << 24 | aStream.getByte() << 16 |
             aStream.getByte() << 8 | aStream.getByte();
    }
    error(offsize + ' is not a valid offset size');
    return null;
  };

  var offsets = [];
  for (var i = 0; i < count + 1; i++)
    offsets.push(getNextOffset());

  log('Found ' + count + ' objects at offsets :' +
      offsets + ' (offsize: ' + offsize + ')');

  // Now extract the objects
  var relativeOffset = aStream.pos;
  var objects = [];
  for (var i = 0; i < count; i++) {
    var offset = offsets[i];
    aStream.pos = relativeOffset + offset - 1;

    var data = [];
    var length = offsets[i + 1] - 1;
    for (var j = offset - 1; j < length; j++)
      data.push(aIsByte ? aStream.getByte() : aStream.getChar());
    objects.push(data);
  }

  return objects;
}

var Type2Parser = function(aFilePath) {
  var font = new Dict();

  var xhr = new XMLHttpRequest();
  xhr.open('GET', aFilePath, false);
  xhr.mozResponseType = xhr.responseType = 'arraybuffer';
  xhr.expected = (document.URL.indexOf('file:') == 0) ? 0 : 200;
  xhr.send(null);
  this.data = new Stream(xhr.mozResponseArrayBuffer || xhr.mozResponse ||
                         xhr.responseArrayBuffer || xhr.response);

  // Turn on this flag for additional debugging logs
  var debug = false;

  function dump(aStr) {
    if (debug)
      log(aStr);
  };

  function parseAsToken(aString, aMap) {
    var decoded = readFontDictData(aString, aMap);

    var stack = [];
    var count = decoded.length;
    for (var i = 0; i < count; i++) {
      var token = decoded[i];
      if (IsNum(token)) {
        stack.push(token);
      } else {
        switch (token.operand) {
          case 'SID':
            font.set(token.name, CFFStrings[stack.pop()]);
            break;
          case 'number number':
            font.set(token.name, {
              offset: stack.pop(),
              size: stack.pop()
            });
            break;
          case 'boolean':
            font.set(token.name, stack.pop());
            break;
          case 'delta':
            font.set(token.name, stack.pop());
            break;
          default:
            if (token.operand && token.operand.length) {
              var array = [];
              for (var j = 0; j < token.operand.length; j++)
                array.push(stack.pop());
              font.set(token.name, array);
            } else {
              font.set(token.name, stack.pop());
            }
            break;
        }
      }
    }
  };

  this.parse = function(aStream) {
    font.set('major', aStream.getByte());
    font.set('minor', aStream.getByte());
    font.set('hdrSize', aStream.getByte());
    font.set('offsize', aStream.getByte());

    // Move the cursor after the header
    aStream.skip(font.get('hdrSize') - aStream.pos);

    // Read the NAME Index
    dump('Reading Index: Names');
    font.set('Names', readFontIndexData(aStream));
    log('Names: ' + font.get('Names'));

    // Read the Top Dict Index
    dump('Reading Index: TopDict');
    var topDict = readFontIndexData(aStream, true);
    log('TopDict: ' + topDict);

    // Read the String Index
    dump('Reading Index: Strings');
    var strings = readFontIndexData(aStream);
    log('strings: ' + strings);

    // Fill up the Strings dictionary with the new unique strings
    for (var i = 0; i < strings.length; i++)
      CFFStrings.push(strings[i].join(''));

    // Parse the TopDict operator
    var objects = [];
    var count = topDict.length;
    for (var i = 0; i < count; i++)
      parseAsToken(topDict[i], CFFDictDataMap);

    // Read the Global Subr Index that comes just after the Strings Index
    // (cf. "The Compact Font Format Specification" Chapter 16)
    dump('Reading Global Subr Index');
    var subrs = readFontIndexData(aStream, true);
    dump(subrs);

    // Reading Private Dict
    var priv = font.get('Private');
    log('Reading Private Dict (offset: ' + priv.offset +
        ' size: ' + priv.size + ')');
    aStream.pos = priv.offset;

    var privateDict = [];
    for (var i = 0; i < priv.size; i++)
      privateDict.push(aStream.getByte());
    dump('private:' + privateDict);
    parseAsToken(privateDict, CFFDictPrivateDataMap);

    for (var p in font.map)
      dump(p + '::' + font.get(p));

    // Read CharStrings Index
    var charStringsOffset = font.get('CharStrings');
    dump('Read CharStrings Index (offset: ' + charStringsOffset + ')');
    aStream.pos = charStringsOffset;
    var charStrings = readFontIndexData(aStream, true);

    // Read Charset
    dump('Read Charset for ' + charStrings.length + ' glyphs');
    var charsetEntry = font.get('charset');
    if (charsetEntry == 0) {
      error('Need to support CFFISOAdobeCharset');
    } else if (charsetEntry == 1) {
      error('Need to support CFFExpert');
    } else if (charsetEntry == 2) {
      error('Need to support CFFExpertSubsetCharset');
    } else {
      aStream.pos = charsetEntry;
      var charset = readCharset(aStream, charStrings);
    }
  }
};

/*
 * To try the Type2 decoder on a local file in the current directory:
 *
 *  var cff = new Type2Parser("file.cff");
 *  cff.parse(this.data);
 *
 * To try the Type2 decoder on a custom built CFF array:
 *
 *  var file = new Uint8Array(cffFileArray, 0, cffFileSize);
 *  var parser = new Type2Parser();
 *  parser.parse(new Stream(file));
 *
 */

/**
 * Write to a file to the disk (works only on Firefox in privilege mode)
 * but this is useful for dumping a font file to the disk and check with
 * fontforge or the ots program what's wrong with the file.
 *
 * writeToFile(fontData, "/tmp/pdf.js." + fontCount + ".cff");
 */
function writeToFile(aBytes, aFilePath) {
  if (!('netscape' in window))
    return;

  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
  var Cc = Components.classes,
      Ci = Components.interfaces;
  var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
  file.initWithPath(aFilePath);

  var stream = Cc['@mozilla.org/network/file-output-stream;1']
                 .createInstance(Ci.nsIFileOutputStream);
  stream.init(file, 0x04 | 0x08 | 0x20, 0x180, 0);

  var bos = Cc['@mozilla.org/binaryoutputstream;1']
              .createInstance(Ci.nsIBinaryOutputStream);
  bos.setOutputStream(stream);
  bos.writeByteArray(aBytes, aBytes.length);
  stream.close();
}

<|endoftext|>


<commit_before><commit_msg>workers view now auto updates<commit_after><|endoftext|>


<commit_before>import {Log} from 'gameboard';

var unidentified = 'untitled';
var unidentifiedCounter = 0;

class Group {
  constructor() {
    this.length = 0;

    this.ids = {};
    this.tags = {};
    this.names = {};
    this.types = {};
  }

  push(obj) {
    var {name, tags, id} = obj;

    name = name || (unidentified + unidentifiedCounter++);
    id = id || (unidentified + unidentifiedCounter++);
    tags = tags || [];

    if (this.ids[id] != null || this.names[name] != null) {
      Log.w('An object with the same name or id already exists');
      return;
    }

    var currentLength = Object.keys(this.ids);
    this.ids[id] = obj;

    Object.keys(this.tags).forEach(tag => {
      this.tags[tag] = this.tags[tag] || [];
      this.tags[tag].push(currentLength);
    });

    this.names[name] = this.length;

    if (obj.type != null) {
      this.types[obj.type] = this.types[obj.type] || [];
      this.types[obj.type].push(currentLength);
    }

    return this.length = this.values().length;
  }

  pop() {
    var ids = Object.keys(this.ids);

    for (var i = ids.length, j = 0; j > i; i--) {
      var obj = this.ids[ids[i]];

      if (obj != null) {
        this.ids[ids[i]] = null;
        return obj;
      }
    }
  }

  values() {
    return Object.keys(this.ids)
      .filter(id => id != null)
      .map(id => this.ids[id]);
  }

  all(filter) {
    var objects = [];

    var recurse = function(group) {
      group.forEach(obj => {
        if (filter) {
          if (filter(obj)) {
            objects.push(obj);
          }
        } else {
          objects.push(obj);
        }

        if (obj.children && obj.children instanceof Group) {
          recurse(obj.children);
        }
      });
    };

    recurse(this);

    return objects;
  }

  forEach(callback) {
    this.all().forEach(obj => callback(obj));
  }

  map(callback) {
    var mappedArray = new Group();

    this.forEach(obj => mappedArray.push(callback(obj)));

    return mappedArray;
  }

  filter(callback) {
    var filteredArray = new Group();

    this.forEach(obj => {
      if (callback(obj)) {
        filteredArray.push(obj);
      }
    });

    return filteredArray;
  }

  byType(type) {
    return this.types[type].map(index => this[index]);
  }

  byName(name) {
    return this[this.names[name]];
  }

  byTag(tag) {
    return this.tags[tag].map(index => this[index]);
  }

  select(selector) {

  }

  toJSON() {
    return this.values();
  }

  toString() {
    return JSON.stringify(this.values());
  }

  static fromJSON(arr) {
    var group = new Group();

    arr.forEach(obj => group.push(obj));

    return group;
  }

  static fromString(str) {
    return Group.fromJSON(JSON.parse(str));
  }

  remove(index) {
    var id = Object.keys(ids)[index];

    var obj = this.ids[id];

    if (obj == null) {
      Log.w(`Object at ${index} does not exist`);
    }

    var {name, tags} = obj;

    this.ids[id] = null;
    this.names[name] = null;

    this.tags.forEach(tag => {
      var position = tag.indexOf(index);

      if (position >= 0) {
        if (tag.length === 1) {
          this.tags[tag] = [];
        } else {
          this.tags[tag].splice(position, 1);
        }
      }
    });

    this.length = all().length;
  }

  removeByName(name) {
    var index = this.names[name];
    this.remove(index);
  }

  removeByTag(tags) {
    if (!Array.isArray(tags)) {
      tags = [tags];
    }

    tags.forEach(tag => {
      this.tags[tag].forEach(index => this.remove(index));
      this.tags = [];
    });
  }
}

export default Group;
<commit_msg>Update forEach reference<commit_after>import {Log} from 'gameboard';

var unidentified = 'untitled';
var unidentifiedCounter = 0;

class Group {
  constructor() {
    this.length = 0;

    this.ids = {};
    this.tags = {};
    this.names = {};
    this.types = {};
  }

  push(obj) {
    var {name, tags, id} = obj;

    name = name || (unidentified + unidentifiedCounter++);
    id = id || (unidentified + unidentifiedCounter++);
    tags = tags || [];

    if (this.ids[id] != null || this.names[name] != null) {
      Log.w('An object with the same name or id already exists');
      return;
    }

    var currentLength = Object.keys(this.ids);
    this.ids[id] = obj;

    Object.keys(this.tags).forEach(tag => {
      this.tags[tag] = this.tags[tag] || [];
      this.tags[tag].push(currentLength);
    });

    this.names[name] = this.length;

    if (obj.type != null) {
      this.types[obj.type] = this.types[obj.type] || [];
      this.types[obj.type].push(currentLength);
    }

    return this.length = this.values().length;
  }

  pop() {
    var ids = Object.keys(this.ids);

    for (var i = ids.length, j = 0; j > i; i--) {
      var obj = this.ids[ids[i]];

      if (obj != null) {
        this.ids[ids[i]] = null;
        return obj;
      }
    }
  }

  values() {
    return Object.keys(this.ids)
      .filter(id => id != null)
      .map(id => this.ids[id]);
  }

  all(filter) {
    var objects = [];

    var recurse = function(group) {
      group.forEach(obj => {
        if (filter) {
          if (filter(obj)) {
            objects.push(obj);
          }
        } else {
          objects.push(obj);
        }

        if (obj.children && obj.children instanceof Group) {
          recurse(obj.children);
        }
      });
    };

    recurse(this);

    return objects;
  }

  forEach(callback) {
    this.values().forEach(obj => callback(obj));
  }

  map(callback) {
    var mappedArray = new Group();

    this.forEach(obj => mappedArray.push(callback(obj)));

    return mappedArray;
  }

  filter(callback) {
    var filteredArray = new Group();

    this.forEach(obj => {
      if (callback(obj)) {
        filteredArray.push(obj);
      }
    });

    return filteredArray;
  }

  byType(type) {
    return this.types[type].map(index => this[index]);
  }

  byName(name) {
    return this[this.names[name]];
  }

  byTag(tag) {
    return this.tags[tag].map(index => this[index]);
  }

  select(selector) {

  }

  toJSON() {
    return this.values();
  }

  toString() {
    return JSON.stringify(this.values());
  }

  static fromJSON(arr) {
    var group = new Group();

    arr.forEach(obj => group.push(obj));

    return group;
  }

  static fromString(str) {
    return Group.fromJSON(JSON.parse(str));
  }

  remove(index) {
    var id = Object.keys(ids)[index];

    var obj = this.ids[id];

    if (obj == null) {
      Log.w(`Object at ${index} does not exist`);
    }

    var {name, tags} = obj;

    this.ids[id] = null;
    this.names[name] = null;

    this.tags.forEach(tag => {
      var position = tag.indexOf(index);

      if (position >= 0) {
        if (tag.length === 1) {
          this.tags[tag] = [];
        } else {
          this.tags[tag].splice(position, 1);
        }
      }
    });

    this.length = all().length;
  }

  removeByName(name) {
    var index = this.names[name];
    this.remove(index);
  }

  removeByTag(tags) {
    if (!Array.isArray(tags)) {
      tags = [tags];
    }

    tags.forEach(tag => {
      this.tags[tag].forEach(index => this.remove(index));
      this.tags = [];
    });
  }
}

export default Group;
<|endoftext|>


<commit_before>current_tab_id = '#education_nav_item';
updateActiveTab(current_tab_id);

function educationDataHandler(store) {
    // This is working now! Just need to start doing stuff
    console.log(store);
    console.log('ehre');
    console.log(new Date().getTime());
}

console.log(new Date().getTime());
loadGraphData(educationDataHandler);
<commit_msg>Added scaffolding code to start extracting objects from the graph<commit_after>current_tab_id = '#education_nav_item';
updateActiveTab(current_tab_id);

var store_test;

var output = [];

function storeResults(res) {
    output.push(res);
}

function onDone() {
    // Deal with 'output' object here
    // Need to recursively get all the shit we need
    // Sorting output
    output.sort(compareDataDesc);
}

function educationDataHandler(store) {
    // This is working now! Just need to start doing stuff

    getOfType(store, 'Degree', storeResults, onDone)
}

loadGraphData(educationDataHandler);
<|endoftext|>