<commit_before>/*jshint node:true, laxcomma:true, expr:true, newcap:false*/
"use strict";

var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});

requirejs(['http', 'path', 'express', './routes', 'socket.io', 'underscore', './functions.json'], function (http, path, express, routes, socketio, _, underscoreFns) {
  var app = express()
    , server = http.createServer(app)
    , logging = true
    , io = socketio.listen(server, {origins: '*:*', log: logging});

  app.configure(function() {
    app.set('port', process.env.PORT || 3000);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(app.router);
    app.use(express.static(path.join(__dirname, '../client')));
  });

  app.get('/', routes.index);

  // App-specific logging function. Logs messages only if 'logging' var is set to true.
  var log = function(message) {
    if (logging) { console.log(message); }
  };

  // Room constructor function
  var Room = function(){
    var users = [];
    return _.extend(Object.create(Room), {

      isFull: function(){
        return users.length >= 2;
      },

      addUser: function(user){
        if (this.isFull()) {
          throw new Error("Cannot add users to a full room.");
        }
        return users.push(user);
      },

      getUsers: function(){
        return users;
      }

    });
  };

  // Player factory
  var createUser = function(client){
    return {client: client};
  };

  // Create a room when we initialize the server
  var currentRoom = Room();
  // Create a container to hold full rooms
  var prevRooms = [];

  io.sockets.on('connection', function (client) {
    var user = createUser(client);

    if( currentRoom.isFull() ){
      prevRooms.push(currentRoom);
      currentRoom = Room();
    }

    currentRoom.addUser(user);

    client.on('editorChange', function(message) {
      client.broadcast.emit('updateEditor', message);
    });

    client.on('disconnect',function(){
      console.log('lol bai');
    });
  });

  server.listen(app.get('port'), function() {
    console.log("Underscoreboard server listening on port " + app.get('port'));
  });

});
<commit_msg>Added ID generation utility<commit_after>/*jshint node:true, laxcomma:true, expr:true, newcap:false*/
"use strict";

var requirejs = require('requirejs');
requirejs.config({nodeRequire: require});

requirejs(['http', 'path', 'express', './routes', 'socket.io', 'underscore', './functions.json'], function (http, path, express, routes, socketio, _, underscoreFns) {
  var app = express()
    , server = http.createServer(app)
    , logging = true
    , io = socketio.listen(server, {origins: '*:*', log: logging});

  app.configure(function() {
    app.set('port', process.env.PORT || 3000);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(app.router);
    app.use(express.static(path.join(__dirname, '../client')));
  });

  app.get('/', routes.index);

  // App-specific logging function. Logs messages only if 'logging' var is set to true.
  var log = function(message) {
    if (logging) { console.log(message); }
  };

  // ID generator utility function
  var makeId = function(len) {
      var id, CHARSET;
      CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      id = "";

      for (var i = 0, idLen = len || 10; i < idLen; i++) {
          id += CHARSET.charAt(Math.floor(Math.random() * CHARSET.length));
      }

      return id;
  };

  // Room constructor function
  var Room = function(){
    var users = [];
    return _.extend(Object.create(Room), {

      isFull: function(){
        return users.length >= 2;
      },

      addUser: function(user){
        if (this.isFull()) {
          throw new Error("Cannot add users to a full room.");
        }
        return users.push(user);
      },

      getUsers: function(){
        return users;
      }

    });
  };

  // Player factory
  var createUser = function(client){
    return {client: client};
  };

  // Create a room when we initialize the server
  var currentRoom = Room();
  // Create a container to hold full rooms
  var prevRooms = [];

  io.sockets.on('connection', function (client) {
    var user = createUser(client);

    if( currentRoom.isFull() ){
      prevRooms.push(currentRoom);
      currentRoom = Room();
    }

    currentRoom.addUser(user);

    client.on('editorChange', function(message) {
      client.broadcast.emit('updateEditor', message);
    });

    client.on('disconnect',function(){
      console.log('lol bai');
    });
  });

  server.listen(app.get('port'), function() {
    console.log("Underscoreboard server listening on port " + app.get('port'));
  });

});
<|endoftext|>


<commit_before>/*
 * flexselect: a jQuery plugin, version: %RELEASE_VERSION% (%RELEASE_DATE%)
 * @requires jQuery v1.3 or later
 *
 * FlexSelect is a jQuery plugin that makes it easy to convert a select box into
 * a Quicksilver-style, autocompleting, flex matching selection tool.
 *
 * For usage and examples, visit:
 * http://rmm5t.github.com/jquery-flexselect/
 *
 * Licensed under the MIT:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright (c) 2009, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org)
 */
(function($) {
  $.flexselect = function(select, options) { this.init(select, options); };

  $.extend($.flexselect.prototype, {
    settings: {
      allowMismatch: false,
      selectedClass: "flexselect_selected",
      dropdownClass: "flexselect_dropdown",
      inputIdTransform:    function(id)   { return id + "_flexselect"; },
      inputNameTransform:  function(name) { return; },
      dropdownIdTransform: function(id)   { return id + "_flexselect_dropdown"; }
    },
    select: null,
    input: null,
    hidden: null,
    dropdown: null,
    dropdownList: null,
    cache: [],
    results: [],
    lastAbbreviation: null,
    abbreviationBeforeFocus: null,
    selectedIndex: 0,
    picked: false,
    dropdownMouseover: false, // Workaround for poor IE behaviors

    init: function(select, options) {
      this.settings = $.extend({}, this.settings, options);
      this.select = $(select);
      this.preloadCache();
      this.renderControls();
      this.wire();
    },

    preloadCache: function() {
      this.cache = this.select.children("option").map(function() {
        return { name: $.trim($(this).text()), value: $(this).val(), score: 0.0 };
      });
    },

    renderControls: function() {
      var selected = this.select.children("option:selected");

      this.hidden = $("<input type='hidden'/>").attr({
        id: this.select.attr("id"),
        name: this.select.attr("name")
      }).val(selected.val());

      this.input = $("<input type='text' autocomplete='off' />").attr({
        id: this.settings.inputIdTransform(this.select.attr("id")),
        name: this.settings.inputNameTransform(this.select.attr("name")),
        accesskey: this.select.attr("accesskey"),
        tabindex: this.select.attr("tabindex"),
        style: this.select.attr("style")
      }).addClass(this.select.attr("class")).val($.trim(selected.text()));

      this.dropdown = $("

").attr({
        id: this.settings.dropdownIdTransform(this.select.attr("id"))
      }).addClass(this.settings.dropdownClass);
      this.dropdownList = $("

");
      this.dropdown.append(this.dropdownList);

      this.select.after(this.input).after(this.hidden).remove();
      $("body").append(this.dropdown);
    },

    wire: function() {
      var self = this;

      this.input.click(function() {
        self.lastAbbreviation = null;
        self.focus();
      });

      this.input.mouseup(function(event) {
        // This is so Safari selection actually occurs.
        event.preventDefault();
      });

      this.input.focus(function() {
        self.abbreviationBeforeFocus = self.input.val();
        self.input.select();
        if (!self.picked) self.filterResults();
      });

      this.input.blur(function() {
        if (!self.dropdownMouseover) {
          self.hide();
          if (!self.settings.allowMismatch && !self.picked) self.reset();
        }
      });

      this.dropdownList.mouseover(function (event) {
        if (event.target.tagName == "LI") {
          var rows = self.dropdown.find("li");
          self.markSelected(rows.index($(event.target)));
        }
      });
      this.dropdownList.mouseleave(function () {
        self.markSelected(-1);
      });
      this.dropdownList.mouseup(function (event) {
        self.pickSelected();
        self.focusAndHide();
      });
      this.dropdown.mouseover(function (event) {
        self.dropdownMouseover = true;
      });
      this.dropdown.mouseleave(function (event) {
        self.dropdownMouseover = false;
      });
      this.dropdown.mousedown(function (event) {
        event.preventDefault();
      });

      this.input.keyup(function(event) {
        switch (event.keyCode) {
          case 13: // return
            event.preventDefault();
            self.pickSelected();
            self.focusAndHide();
            break;
          case 27: // esc
            event.preventDefault();
            self.reset();
            self.focusAndHide();
            break;
          default:
            self.filterResults();
            break;
        }
      });

      this.input.keydown(function(event) {
        switch (event.keyCode) {
          case 9:  // tab
            self.pickSelected();
            self.hide();
            break;
          case 33: // pgup
            event.preventDefault();
            self.markFirst();
            break;
          case 34: // pgedown
            event.preventDefault();
            self.markLast();
            break;
          case 38: // up
            event.preventDefault();
            self.moveSelected(-1);
            break;
          case 40: // down
            event.preventDefault();
            self.moveSelected(1);
            break;
          case 13: // return
          case 27: // esc
            event.preventDefault();
            event.stopPropagation();
            break;
        }
      });
    },

    filterResults: function() {
      var abbreviation = this.input.val();
      if (abbreviation == this.lastAbbreviation) return;

      var results = [];
      $.each(this.cache, function() {
        this.score = LiquidMetal.score(this.name, abbreviation);
        if (this.score > 0.0) results.push(this);
      });
      this.results = results;

      this.sortResults();
      this.renderDropdown();
      this.markFirst();
      this.lastAbbreviation = abbreviation;
      this.picked = false;
    },

    sortResults: function() {
      this.results.sort(function(a, b) { return b.score - a.score; });
    },

    renderDropdown: function() {
      var dropdownBorderWidth = this.dropdown.outerWidth() - this.dropdown.innerWidth();
      var inputOffset = this.input.offset();
      this.dropdown.css({
        width: (this.input.outerWidth() - dropdownBorderWidth) + "px",
        top: (inputOffset.top + this.input.outerHeight()) + "px",
        left: inputOffset.left + "px"
      });

      var list = this.dropdownList.html("");
      $.each(this.results, function() {
        // list.append($("
").html(this.name + " [" + Math.round(this.score*100)/100 + "]"));
        list.append($("
").html(this.name));
      });
      this.dropdown.show();
    },

    markSelected: function(n) {
      if (n > this.results.length) return;

      var rows = this.dropdown.find("li");
      rows.removeClass(this.settings.selectedClass);
      this.selectedIndex = n;

      if (n >= 0) $(rows[n]).addClass(this.settings.selectedClass);
    },

    pickSelected: function() {
      var selected = this.results[this.selectedIndex];
      if (selected) {
        this.input.val(selected.name);
        this.hidden.val(selected.value);
        this.picked = true;
      } else if (this.settings.allowMismatch) {
        this.hidden.val("");
      } else {
        this.reset();
      }
    },

    hide: function() {
      this.dropdown.hide();
      this.lastAbbreviation = null;
    },

    moveSelected: function(n) { this.markSelected(this.selectedIndex+n); },
    markFirst:    function()  { this.markSelected(0); },
    markLast:     function()  { this.markSelected(this.results.length - 1); },
    reset:        function()  { this.input.val(this.abbreviationBeforeFocus); },
    focus:        function()  { this.input.focus(); },
    focusAndHide: function()  { this.focus(); this.hide(); }
  });

  $.fn.flexselect = function(options) {
    this.each(function() {
      if (this.tagName == "SELECT") new $.flexselect(this, options);
    });
    return this;
  };
})(jQuery);
<commit_msg>Add hideDropdownListIfNoInput as setting parameter, so that if the input is blank, the drop down list will not show the whole list.<commit_after>/*
 * flexselect: a jQuery plugin, version: %RELEASE_VERSION% (%RELEASE_DATE%)
 * @requires jQuery v1.3 or later
 *
 * FlexSelect is a jQuery plugin that makes it easy to convert a select box into
 * a Quicksilver-style, autocompleting, flex matching selection tool.
 *
 * For usage and examples, visit:
 * http://rmm5t.github.com/jquery-flexselect/
 *
 * Licensed under the MIT:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright (c) 2009, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org)
 */
(function($) {
  $.flexselect = function(select, options) { this.init(select, options); };

  $.extend($.flexselect.prototype, {
    settings: {
      allowMismatch: false,
	  hideDropdownListIfNoInput: false,
      selectedClass: "flexselect_selected",
      dropdownClass: "flexselect_dropdown",
      inputIdTransform:    function(id)   { return id + "_flexselect"; },
      inputNameTransform:  function(name) { return; },
      dropdownIdTransform: function(id)   { return id + "_flexselect_dropdown"; }
    },
    select: null,
    input: null,
    hidden: null,
    dropdown: null,
    dropdownList: null,
    cache: [],
    results: [],
    lastAbbreviation: null,
    abbreviationBeforeFocus: null,
    selectedIndex: 0,
    picked: false,
    dropdownMouseover: false, // Workaround for poor IE behaviors

    init: function(select, options) {
      this.settings = $.extend({}, this.settings, options);
      this.select = $(select);
      this.preloadCache();
      this.renderControls();
      this.wire();
    },

    preloadCache: function() {
      this.cache = this.select.children("option").map(function() {
        return { name: $.trim($(this).text()), value: $(this).val(), score: 0.0 };
      });
    },

    renderControls: function() {
      var selected = this.select.children("option:selected");

      this.hidden = $("<input type='hidden'/>").attr({
        id: this.select.attr("id"),
        name: this.select.attr("name")
      }).val(selected.val());

      this.input = $("<input type='text' autocomplete='off' />").attr({
        id: this.settings.inputIdTransform(this.select.attr("id")),
        name: this.settings.inputNameTransform(this.select.attr("name")),
        accesskey: this.select.attr("accesskey"),
        tabindex: this.select.attr("tabindex"),
        style: this.select.attr("style")
      }).addClass(this.select.attr("class")).val($.trim(selected.text()));

      this.dropdown = $("

").attr({
        id: this.settings.dropdownIdTransform(this.select.attr("id"))
      }).addClass(this.settings.dropdownClass);
      this.dropdownList = $("

");
      this.dropdown.append(this.dropdownList);

      this.select.after(this.input).after(this.hidden).remove();
      $("body").append(this.dropdown);
    },

    wire: function() {
      var self = this;

      this.input.click(function() {
        self.lastAbbreviation = null;
        self.focus();
      });

      this.input.mouseup(function(event) {
        // This is so Safari selection actually occurs.
        event.preventDefault();
      });

      this.input.focus(function() {
        self.abbreviationBeforeFocus = self.input.val();
        self.input.select();
        if (!self.picked) self.filterResults();
      });

      this.input.blur(function() {
        if (!self.dropdownMouseover) {
          self.hide();
          if (!self.settings.allowMismatch && !self.picked) self.reset();
        }
		if(self.settings.hideDropdownListIfNoInput)
			self.dropdownList.show();
      });

      this.dropdownList.mouseover(function (event) {
        if (event.target.tagName == "LI") {
          var rows = self.dropdown.find("li");
          self.markSelected(rows.index($(event.target)));
        }
      });
      this.dropdownList.mouseleave(function () {
        self.markSelected(-1);
      });
      this.dropdownList.mouseup(function (event) {
        self.pickSelected();
        self.focusAndHide();
      });
      this.dropdown.mouseover(function (event) {
        self.dropdownMouseover = true;
      });
      this.dropdown.mouseleave(function (event) {
        self.dropdownMouseover = false;
      });
      this.dropdown.mousedown(function (event) {
        event.preventDefault();
      });

      this.input.keyup(function(event) {
        switch (event.keyCode) {
          case 13: // return
            event.preventDefault();
            self.pickSelected();
            self.focusAndHide();
            break;
          case 27: // esc
            event.preventDefault();
            self.reset();
            self.focusAndHide();
            break;
          default:
            self.filterResults();
            break;
        }
		if(self.settings.hideDropdownListIfNoInput){
			if(self.input.val() == "")
				self.dropdownList.hide();
			else
				self.dropdownList.show();
		}
      });

      this.input.keydown(function(event) {
        switch (event.keyCode) {
          case 9:  // tab
            self.pickSelected();
            self.hide();
            break;
          case 33: // pgup
            event.preventDefault();
            self.markFirst();
            break;
          case 34: // pgedown
            event.preventDefault();
            self.markLast();
            break;
          case 38: // up
            event.preventDefault();
            self.moveSelected(-1);
            break;
          case 40: // down
            event.preventDefault();
            self.moveSelected(1);
            break;
          case 13: // return
          case 27: // esc
            event.preventDefault();
            event.stopPropagation();
            break;
        }
      });
    },

    filterResults: function() {
      var abbreviation = this.input.val();
      if (abbreviation == this.lastAbbreviation) return;

      var results = [];
      $.each(this.cache, function() {
        this.score = LiquidMetal.score(this.name, abbreviation);
        if (this.score > 0.0) results.push(this);
      });
      this.results = results;

      this.sortResults();
      this.renderDropdown();
      this.markFirst();
      this.lastAbbreviation = abbreviation;
      this.picked = false;
    },

    sortResults: function() {
      this.results.sort(function(a, b) { return b.score - a.score; });
    },

    renderDropdown: function() {
      var dropdownBorderWidth = this.dropdown.outerWidth() - this.dropdown.innerWidth();
      var inputOffset = this.input.offset();
      this.dropdown.css({
        width: (this.input.outerWidth() - dropdownBorderWidth) + "px",
        top: (inputOffset.top + this.input.outerHeight()) + "px",
        left: inputOffset.left + "px"
      });

      var list = this.dropdownList.html("");
      $.each(this.results, function() {
        // list.append($("
").html(this.name + " [" + Math.round(this.score*100)/100 + "]"));
        list.append($("
").html(this.name));
      });
      this.dropdown.show();
    },

    markSelected: function(n) {
      if (n > this.results.length) return;

      var rows = this.dropdown.find("li");
      rows.removeClass(this.settings.selectedClass);
      this.selectedIndex = n;

      if (n >= 0) $(rows[n]).addClass(this.settings.selectedClass);
    },

    pickSelected: function() {
      var selected = this.results[this.selectedIndex];
      if (selected) {
        this.input.val(selected.name);
        this.hidden.val(selected.value);
        this.picked = true;
      } else if (this.settings.allowMismatch) {
        this.hidden.val("");
      } else {
        this.reset();
      }
    },

    hide: function() {
      this.dropdown.hide();
      this.lastAbbreviation = null;
    },

    moveSelected: function(n) { this.markSelected(this.selectedIndex+n); },
    markFirst:    function()  { this.markSelected(0); },
    markLast:     function()  { this.markSelected(this.results.length - 1); },
    reset:        function()  { this.input.val(this.abbreviationBeforeFocus); },
    focus:        function()  { this.input.focus(); },
    focusAndHide: function()  { this.focus(); this.hide(); }
  });

  $.fn.flexselect = function(options) {
    this.each(function() {
      if (this.tagName == "SELECT") new $.flexselect(this, options);
    });
    return this;
  };
})(jQuery);
<|endoftext|>


<commit_before>require(['jquery'], function($) {
	var Customize = {
		onClick: function(e) {
			console.log("Clicked Wizard", "event", e, "this", this);
			this.updateWizard();
		},
		updateWizard: function() {
			console.log("Updating Wizard...");
			this.remove('wizard_add_students');
			this.replaceText("wizard_add_tas", /TA(s?)/g, "TF$1");
		},
		remove: function(id) {
			$("#"+id).remove();
		},
		replaceText: function(id, pattern, replacement) {
			var $itemEl = $("#"+id);
			var $boxEl = this.getMessageBoxEl();
			var that = this;
			console.log("replaceText", id, pattern, replacement);

			// Replace text on the checklist
			that._replaceText($itemEl, pattern, replacement);

			// When the checklist item is clicked, replace text in the message box
			$itemEl.on("click", function(e) {
				console.log("clicked", e, $boxEl);
				that._replaceText($boxEl, pattern, replacement);
			});
		},
		_replaceText: function($el, pattern, replacement) {
			// Replace all descendant text node values
			$el.find("*").contents().filter(function () {
				console.log("filtering", this.nodeType);
				return this.nodeType === 3;
			}).each(function() {
				console.log("replacing", $el, this);
				this.nodeValue = this.nodeValue.replace(pattern, replacement);
			});
		},
		getMessageBoxEl: function() {
			return $(".CourseWizard__modalOverlay .ic-wizard-box__message");
		}
	};

	Customize.onClick = $.proxy(Customize.onClick, Customize);

	console.log("setting up jquery test...", Customize);

	$(".wizard_popup_link").on("click", Customize.onClick);
});
<commit_msg>Updated jquery test.<commit_after>require(['jquery'], function($) {

	var Customize = {
		// Event handler for when the "Setup Checklist" button is clicked
		onClick: function(e) {
			console.log("Clicked Wizard", "event", e, "this", this);

			this.removeItem('wizard_add_students');

			this.updateItem({
				id: "wizard_add_tas",
				text: "Add TFs to the Course",
				message: [
					"You may want to assign some TAs to help you with the course. ",
					"TAs can grade student submissions, help moderate the discussions ",
					"and even update due dates and assignment details for you."
				].join(''),
				btn: "Add TFs to the Course"
			});
		},
		// Removes an item from the checklist
		removeItem: function(id) {
			console.log("remove", id);
			$("#"+id).remove();
		},
		// Updates an item in the checklist
		updateItem: function(replacment) {
			console.log("update", replacement);
			var that = this;
			var $el = $("#"+replacement.id);
			$el.text(replacement.text);
			$el.on("click", function(e) {
				var $box = that.getMessageBoxEl();
				$box.find('.ic-wizard-box__message-text').text(replacement.msg);
				$box.find('.ic-wizard-box__message-button').text(replacement.btn);
			});
		},
		// Returns the message box container element
		getMessageBoxEl: function() {
			return $(".CourseWizard__modalOverlay .ic-wizard-box__message");
		}
	};

	// Bind the context of the event handler to the object it is attached to
	Customize.onClick = $.proxy(Customize.onClick, Customize);

	// Attach our customizations to the wizard button
	console.log("setting up jquery test...", Customize);
	$(".wizard_popup_link").on("click", Customize.onClick);
});
<|endoftext|>


<commit_before>(function($){"use strict";function debug(msg){console.log("github:",msg)}function iso8601(date){var year=date.getFullYear(),month=""+date.getMonth()+1,day=""+date.getDate();return year+"-"+(1==month.length?"0"+month:month)+"-"+ +(1==day.length?"0"+day:day)}function ago(date){function pl(qt,unit){var m=Math.ceil(diff/qt),u=unit;return m>1&&(u+="s"),m+" "+u+" ago"}var diff=Date.now()-date.getTime();return 6e4>diff?"less than a minute ago":(diff=Math.ceil(diff/1e3),3600>diff?pl(60,"minute"):86400>diff?pl(3600,"hour"):2678400>diff?pl(86400,"day"):31536e3>diff?pl(2678400,"month"):pl(31536e3,"year"))}function getRepos(cb){var repos=[];$.ajax({url:api_base+"/users/"+settings.user+"/repos",success:function(data){if(!(data instanceof Array))return cb(repos),void 0;for(var i=0;data.length>i;i++){var repo=data[i];repos.push({name:repo.name,url:repo.html_url})}cb(repos)}})}function getCommits(repos,cb){function lower(){0==--bar&&complete()}function complete(){commits.sort(function(a,b){return b.date.getTime()-a.date.getTime()}),cb(commits.slice(0,settings.display))}var commits=[],bar=repos.length,since=iso8601(new Date(Date.now()-262974e4));$.each(repos,function(i,repo){$.ajax({url:api_base+"/repos/"+settings.user+"/"+repo.name+"/commits",data:{since:since},success:function(data){if(!(data instanceof Array))return lower(),void 0;for(var i=0;data.length>i;i++){var commit=data[i];commits.push({repo:repo,user:{name:commit.author.login,avatar:commit.author.avatar_url,url:"https://github.com/"+commit.author.login},msg:commit.commit.message,sha:commit.sha,url:"https://github.com/"+settings.user+"/"+repo.name+"/commit/"+commit.sha,tree:"https://github.com/"+settings.user+"/"+repo.name+"/tree/"+commit.sha,date:new Date(Date.parse(commit.commit.author.date))})}lower()}})})}var api_base="https://api.github.com",settings={display:5,user:null};$.fn.github=function(options){var $this=this;for(var key in settings)options.hasOwnProperty(key)&&options[key]!==void 0&&(settings[key]=options[key]);return settings.user?(debug(settings),getRepos(function(repos){debug(repos),getCommits(repos,function(commits){debug(commits);for(var html='

 :stream / '+settings.user+""+"	"+"
",i=0;commits.length>i;i++){var commit=commits[i];html+='
'+"	"+''+''+commit.msg+"
"+'
'+commit.user.name+' '+ago(commit.date)+" to "+''+commit.repo.name+""+"
"+"	"+''+''+commit.sha.substring(0,10)+"
"+'Browse code »'+""+"	"+"
"}html+="
",$this.html(html)})}),void 0):(console.error("github: please provide username"),void 0)}})(jQuery);<commit_msg>add new build<commit_after>(function($){"use strict";function debug(msg){console.log("github:",msg)}function iso8601(date){var year=date.getFullYear(),month=""+date.getMonth()+1,day=""+date.getDate();return year+"-"+(1==month.length?"0"+month:month)+"-"+ +(1==day.length?"0"+day:day)}function ago(date){function pl(qt,unit){var m=Math.ceil(diff/qt),u=unit;return m>1&&(u+="s"),m+" "+u+" ago"}var diff=Date.now()-date.getTime();return 6e4>diff?"less than a minute ago":(diff=Math.ceil(diff/1e3),3600>diff?pl(60,"minute"):86400>diff?pl(3600,"hour"):2678400>diff?pl(86400,"day"):31536e3>diff?pl(2678400,"month"):pl(31536e3,"year"))}function getRepos(cb){var repos=[];$.ajax({url:api_base+"/users/"+settings.user+"/repos",dataType:"json",success:function(data){if(!(data instanceof Array))return cb(repos),void 0;for(var i=0;data.length>i;i++){var repo=data[i];repos.push({name:repo.name,url:repo.html_url})}cb(repos)}})}function getCommits(repos,cb){function lower(){0==--bar&&complete()}function complete(){commits.sort(function(a,b){return b.date.getTime()-a.date.getTime()}),cb(commits.slice(0,settings.display))}var commits=[],bar=repos.length,since=iso8601(new Date(Date.now()-262974e4));$.each(repos,function(i,repo){$.ajax({url:api_base+"/repos/"+settings.user+"/"+repo.name+"/commits",data:{since:since},dataType:"json",success:function(data){if(!(data instanceof Array))return lower(),void 0;for(var i=0;data.length>i;i++){var commit=data[i];commits.push({repo:repo,user:{name:commit.author.login,avatar:commit.author.avatar_url,url:"https://github.com/"+commit.author.login},msg:commit.commit.message,sha:commit.sha,url:"https://github.com/"+settings.user+"/"+repo.name+"/commit/"+commit.sha,tree:"https://github.com/"+settings.user+"/"+repo.name+"/tree/"+commit.sha,date:new Date(Date.parse(commit.commit.author.date))})}lower()}})})}var api_base="https://api.github.com",settings={display:5,user:null};$.fn.github=function(options){var $this=this;for(var key in settings)options.hasOwnProperty(key)&&options[key]!==void 0&&(settings[key]=options[key]);return settings.user?(debug(settings),getRepos(function(repos){debug(repos),getCommits(repos,function(commits){debug(commits);for(var html='

'+settings.user+" • GitHub"+"	"+"
",i=0;commits.length>i;i++){var commit=commits[i];html+='
'+"	"+''+''+commit.msg+"
"+'
'+commit.user.name+' '+ago(commit.date)+" to "+''+commit.repo.name+""+"
"+"	"+''+''+commit.sha.substring(0,10)+"
"+'Browse code »'+""+"	"+"
"}html+="
",$this.html(html)})}),void 0):(console.error("github: please provide username"),void 0)}})(jQuery);<|endoftext|>


<commit_before>import request from '../request/request';

export default class Forum {

  /**
   * Forum
   *
   * @param {String} name forum's load name
   * @return {Forum} `Forum` instance
   * @api public
   */

  constructor (name) {
    this.$_name = name;
  }

  /**
   * Forcefully fetch data from the server
   *
   * @return {Promise}
   * @api public
   */

   fetch () {
    if (this.$_fetch) return this.$_fetch;

    this.$_fetch = new Promise((resolve, reject) => {
      request
        .get('/api/forum/' + this.$_name)
        .end((err, res) => {
          this.$_fetch = null;

          if (err || !res.ok) return reject(err || res.error);

          var u = res.body;

          if (!u.id && !u._id) return reject(new Error('Forum not found'));

          this.set(u);

          resolve(this);
        });
    });

    this.$_lastFetch = this.$_fetch;
    return this.$_fetch;
  }

  /**
   * Loads forum from server only once until unload() is called.
   *
   * @return {Promise} `Promise` instance.
   * @api public
   */

  load () {
    if (this.$_lastFetch) return this.$_lastFetch;
    return this.fetch();
  }

  /**
   * Unloads forum to let again be load()
   *
   * @return {Promise} `Promise` instance.
   * @api public
   */

  unload () {
    this.$_lastFetch = null;
    return this;
  }

  /**
   * Set forum attributes
   *
   * @param {Hash} Forum attributes.
   * @return {Forum} `Forum` instance.
   * @api public
   */

  set (attrs) {
    for (var prop in attrs) {
      if (attrs.hasOwnProperty(prop)) {
        this[prop] = attrs[prop];
      }
    }

    return this;
  }

  /**
   * Cleans up user
   *
   * @api private
   */

  cleanup () {
    for (let i in this) {
      if ('_callbacks' == i) continue;
      if ('_events' == i) continue;
      if ('$' == i.charAt(0)) continue;
      if (!this.hasOwnProperty(i)) continue;
      if ('function' == typeof this[i]) continue;
      delete this[i];
    }
  }

}
<commit_msg>fix forum loading<commit_after>import request from '../request/request';

export default class Forum {

  /**
   * Forum
   *
   * @param {String} name forum's load name
   * @return {Forum} `Forum` instance
   * @api public
   */

  constructor (name) {
    this.$_name = name;
  }

  /**
   * Forcefully fetch data from the server
   *
   * @return {Promise}
   * @api public
   */

   fetch () {
    if (this.$_fetch) return this.$_fetch;

    this.$_fetch = new Promise((resolve, reject) => {
      request
        .get('/api/forum/' + this.$_name)
        .end((err, res) => {
          this.$_fetch = null;

          if (err || !res.ok) return reject(err || res.error);

          var u = res.body;

          if (!u || !u.id) return reject(new Error('Forum not found'));

          this.set(u);

          resolve(this);
        });
    });

    this.$_lastFetch = this.$_fetch;
    return this.$_fetch;
  }

  /**
   * Loads forum from server only once until unload() is called.
   *
   * @return {Promise} `Promise` instance.
   * @api public
   */

  load () {
    if (this.$_lastFetch) return this.$_lastFetch;
    return this.fetch();
  }

  /**
   * Unloads forum to let again be load()
   *
   * @return {Promise} `Promise` instance.
   * @api public
   */

  unload () {
    this.$_lastFetch = null;
    return this;
  }

  /**
   * Set forum attributes
   *
   * @param {Hash} Forum attributes.
   * @return {Forum} `Forum` instance.
   * @api public
   */

  set (attrs) {
    for (var prop in attrs) {
      if (attrs.hasOwnProperty(prop)) {
        this[prop] = attrs[prop];
      }
    }

    return this;
  }

  /**
   * Cleans up user
   *
   * @api private
   */

  cleanup () {
    for (let i in this) {
      if ('_callbacks' == i) continue;
      if ('_events' == i) continue;
      if ('$' == i.charAt(0)) continue;
      if (!this.hasOwnProperty(i)) continue;
      if ('function' == typeof this[i]) continue;
      delete this[i];
    }
  }

}
<|endoftext|>


<commit_before>var RegistryClient = require('../Client'),
    expect = require('expect.js'),
    nock = require('nock');

describe('RegistryClient', function () {

    beforeEach(function () {
        this.uri = 'https://bower.herokuapp.com';
        this.timeoutVal = 5000;
        this.registry = new RegistryClient({
            strictSsl: false
        });
        this.conf = {
            search: [this.uri],
            register: this.uri,
            publish: this.uri
        };
    });

    describe('Constructor', function () {

        describe('instantiating a client', function () {

            it('should provide an instance of RegistryClient', function () {
                expect(this.registry instanceof RegistryClient).to.be.ok;
            });

            it('should set default registry config', function () {
                expect(this.registry._config.registry).to.eql(this.conf);
            });

            it('should set default search config', function () {
                expect(this.registry._config.registry.search[0]).to.eql(this.uri);
            });

            it('should set default register config', function () {
                expect(this.registry._config.registry.register).to.eql(this.uri);
            });

            it('should set default publish config', function () {
                expect(this.registry._config.registry.publish).to.eql(this.uri);
            });

            it('should set default cache path config', function () {
                expect(typeof this.registry._config.cache === 'string').to.be.ok;
            });

            it('should set default timeout config', function () {
                expect(this.registry._config.timeout).to.eql(this.timeoutVal);
            });

            it('should set default strictSsl config', function () {
                expect(this.registry._config.strictSsl).to.be.false;
            });

        });

        it('should have a lookup prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('lookup');
        });

        it('should have a search prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('search');
        });

        it('should have a list prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('list');
        });

        it('should have a register prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('register');
        });

        it('should have a clearCache prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('clearCache');
        });

        it('should have a resetCache prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('resetCache');
        });

        it('should have a clearRuntimeCache static method', function () {
            expect(RegistryClient).to.have.property('clearRuntimeCache');
        });

    });

    describe('instantiating a client with custom options', function () {

        describe('offline', function () {

            it('should not return search results ', function () {
                this.registry._config.offline = true;

                this.registry.search('jquery', function (err, results) {
                    expect(err).to.be.null;
                    expect(results.length).to.eql(0);
                });
            });

        });

    });

    //
    // lookup
    //
    describe('calling the lookup instance method with argument', function () {

        it('should not return an error', function () {
            this.registry.lookup('jquery', function (err) {
                expect(err).to.be.null;
            });
        });

        it('should return entry type', function () {
            this.registry.lookup('jquery', function (err, entry) {
                expect(err).to.be.null;
                expect(entry.type).to.eql('alias');
            });
        });

        it('should return entry url ', function () {
            this.registry.lookup('jquery', function (err, entry) {
                expect(err).to.be.null;
                expect(entry.url).to.eql('git://github.com/components/jquery.git');
            });
        });

    });

    describe('calling the lookup instance method without argument', function () {

        it('should return an error and no result', function () {
            this.registry.lookup('', function (err, entry) {
                expect(err).to.not.be.null;
                expect(entry).to.be.undefined;
            });
        });

    });

    //
    // register
    //
    describe('calling the register instance method with argument', function () {

        beforeEach(function () {
            nock('https://bower.herokuapp.com:443')
              .post('/packages', 'name=test-ba&url=git%3A%2F%2Fgithub.com%2Ftest-ba%2Ftest-ba.git')
              .reply(201);

            this.pkg = 'test-ba';
            this.pkgUrl = 'git://github.com/test-ba/test-ba.git';
        });

        it('should not return an error', function (done) {
            this.registry.register(this.pkg, this.pkgUrl, function (err) {
                expect(err).to.be.null;
                done();
            });
        });

        it('should return entry name', function (done) {
            var self = this;

            this.registry.register(this.pkg, this.pkgUrl, function (err, entry) {
                expect(err).to.be.null;
                expect(entry.name).to.eql(self.pkg);
                done();
            });
        });

        it('should return entry url', function (done) {
            var self = this;

            this.registry.register(this.pkg, this.pkgUrl, function (err, entry) {
                expect(err).to.be.null;
                expect(entry.url).to.eql(self.pkgUrl);
                done();
            });
        });

    });

    describe('calling the register instance method without arguments', function () {
        it('should return an error and no result', function () {
            this.registry.register('', '', function (err, entry) {
                expect(err).to.not.be.null;
                expect(entry).to.be.undefined;
            });
        });
    });

    //
    // search
    //
    describe('calling the search instance method with argument', function () {

        beforeEach(function () {
            nock('https://bower.herokuapp.com:443')
              .get('/packages/search/jquery')
              .replyWithFile(200, __dirname + '/fixtures/search.json');

            this.pkg = 'jquery';
            this.pkgUrl = 'git://github.com/components/jquery.git';
        });

        it('should not return an error', function (done) {
            this.registry.search(this.pkg, function (err) {
                expect(err).to.be.null;
                done();
            });
        });

        it('should return entry name', function (done) {
            var self = this;

            this.registry.search(this.pkg, function (err, results) {
                results.forEach(function (entry) {
                    if (entry.name === self.pkg) {
                        expect(entry.name).to.eql(self.pkg);
                        done();
                    }
                });
            });
        });

        it('should return entry url', function (done) {
            var self = this;

            this.registry.search(this.pkg, function (err, results) {
                results.forEach(function (entry) {
                    if (entry.name === self.pkg) {
                        expect(entry.url).to.eql(self.pkgUrl);
                        done();
                    }
                });
            });
        });

    });

    describe('calling the search instance method without argument', function () {
        it('should return an error and no results', function () {
            this.registry.search('', function (err, results) {
                expect(err).to.not.be.null;
                expect(results).to.be.undefined;
            });
        });
    });

    //
    // clearCache
    //
    describe('called the clearCache instance method with argument', function () {

        beforeEach(function () {
            this.pkg = 'jquery';
        });

        it('should not return an error', function () {
            this.registry.clearCache(this.pkg, function (err) {
                expect(err).to.be.null;
            });
        });
    });

    describe('called the clearCache instance method without argument', function () {

        it('should not return any errors and remove all cache items', function () {
            this.registry.clearCache(function (err) {
                expect(err).to.be.null;
            });
        });
    });

});
<commit_msg>[tests] adds cache test<commit_after>var RegistryClient = require('../Client'),
    fs = require('fs'),
    expect = require('expect.js'),
    nock = require('nock');

describe('RegistryClient', function () {

    beforeEach(function () {
        this.uri = 'https://bower.herokuapp.com';
        this.timeoutVal = 5000;
        this.registry = new RegistryClient({
            strictSsl: false
        });
        this.conf = {
            search: [this.uri],
            register: this.uri,
            publish: this.uri
        };
    });

    describe('Constructor', function () {

        describe('instantiating a client', function () {

            it('should provide an instance of RegistryClient', function () {
                expect(this.registry instanceof RegistryClient).to.be.ok;
            });

            it('should set default registry config', function () {
                expect(this.registry._config.registry).to.eql(this.conf);
            });

            it('should set default search config', function () {
                expect(this.registry._config.registry.search[0]).to.eql(this.uri);
            });

            it('should set default register config', function () {
                expect(this.registry._config.registry.register).to.eql(this.uri);
            });

            it('should set default publish config', function () {
                expect(this.registry._config.registry.publish).to.eql(this.uri);
            });

            it('should set default cache path config', function () {
                expect(typeof this.registry._config.cache === 'string').to.be.ok;
            });

            it('should set default timeout config', function () {
                expect(this.registry._config.timeout).to.eql(this.timeoutVal);
            });

            it('should set default strictSsl config', function () {
                expect(this.registry._config.strictSsl).to.be.false;
            });

        });

        it('should have a lookup prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('lookup');
        });

        it('should have a search prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('search');
        });

        it('should have a list prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('list');
        });

        it('should have a register prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('register');
        });

        it('should have a clearCache prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('clearCache');
        });

        it('should have a resetCache prototype method', function () {
            expect(RegistryClient.prototype).to.have.property('resetCache');
        });

        it('should have a clearRuntimeCache static method', function () {
            expect(RegistryClient).to.have.property('clearRuntimeCache');
        });

    });

    describe('instantiating a client with custom options', function () {

        describe('offline', function () {

            it('should not return search results ', function () {
                this.registry._config.offline = true;

                this.registry.search('jquery', function (err, results) {
                    expect(err).to.be.null;
                    expect(results.length).to.eql(0);
                });
            });

        });

        describe('cache', function () {

            beforeEach(function () {
                nock('https://bower.herokuapp.com:443')
                  .get('/packages/search/jquery')
                  .replyWithFile(200, __dirname + '/fixtures/search.json');

                this.client = new RegistryClient({
                    cache: __dirname + '/cache',
                    strictSsl: false
                });

            });

            it('should fill cache', function (done) {

                var cacheDir = this.client._config.cache;
                var host = 'bower.herokuapp.com';
                var method = 'search';
                var pkg = 'jquery';
                var self = this;

                var path = cacheDir + '/' + host + '/' + method + '/' + pkg;

                self.client.search(pkg, function (err, results) {
                    expect(err).to.be.null;
                    expect(results.length).to.eql(334);

                    fs.exists(path, function (exists) {
                        expect(exists).to.be.true;
                        done();
                    });
                });

            });

            it.skip('should read results from cache', function () { });
        });
    });

    //
    // lookup
    //
    describe('calling the lookup instance method with argument', function () {

        it('should not return an error', function () {
            this.registry.lookup('jquery', function (err) {
                expect(err).to.be.null;
            });
        });

        it('should return entry type', function () {
            this.registry.lookup('jquery', function (err, entry) {
                expect(err).to.be.null;
                expect(entry.type).to.eql('alias');
            });
        });

        it('should return entry url ', function () {
            this.registry.lookup('jquery', function (err, entry) {
                expect(err).to.be.null;
                expect(entry.url).to.eql('git://github.com/components/jquery.git');
            });
        });

    });

    describe('calling the lookup instance method without argument', function () {

        it('should return an error and no result', function () {
            this.registry.lookup('', function (err, entry) {
                expect(err).to.not.be.null;
                expect(entry).to.be.undefined;
            });
        });

    });

    //
    // register
    //
    describe('calling the register instance method with argument', function () {

        beforeEach(function () {
            nock('https://bower.herokuapp.com:443')
              .post('/packages', 'name=test-ba&url=git%3A%2F%2Fgithub.com%2Ftest-ba%2Ftest-ba.git')
              .reply(201);

            this.pkg = 'test-ba';
            this.pkgUrl = 'git://github.com/test-ba/test-ba.git';
        });

        it('should not return an error', function (done) {
            this.registry.register(this.pkg, this.pkgUrl, function (err) {
                expect(err).to.be.null;
                done();
            });
        });

        it('should return entry name', function (done) {
            var self = this;

            this.registry.register(this.pkg, this.pkgUrl, function (err, entry) {
                expect(err).to.be.null;
                expect(entry.name).to.eql(self.pkg);
                done();
            });
        });

        it('should return entry url', function (done) {
            var self = this;

            this.registry.register(this.pkg, this.pkgUrl, function (err, entry) {
                expect(err).to.be.null;
                expect(entry.url).to.eql(self.pkgUrl);
                done();
            });
        });

    });

    describe('calling the register instance method without arguments', function () {
        it('should return an error and no result', function () {
            this.registry.register('', '', function (err, entry) {
                expect(err).to.not.be.null;
                expect(entry).to.be.undefined;
            });
        });
    });

    //
    // search
    //
    describe('calling the search instance method with argument', function () {

        beforeEach(function () {
            nock('https://bower.herokuapp.com:443')
              .get('/packages/search/jquery')
              .replyWithFile(200, __dirname + '/fixtures/search.json');

            this.pkg = 'jquery';
            this.pkgUrl = 'git://github.com/components/jquery.git';
        });

        it('should not return an error', function (done) {
            this.registry.search(this.pkg, function (err) {
                expect(err).to.be.null;
                done();
            });
        });

        it('should return entry name', function (done) {
            var self = this;

            this.registry.search(this.pkg, function (err, results) {
                results.forEach(function (entry) {
                    if (entry.name === self.pkg) {
                        expect(entry.name).to.eql(self.pkg);
                        done();
                    }
                });
            });
        });

        it('should return entry url', function (done) {
            var self = this;

            this.registry.search(this.pkg, function (err, results) {
                results.forEach(function (entry) {
                    if (entry.name === self.pkg) {
                        expect(entry.url).to.eql(self.pkgUrl);
                        done();
                    }
                });
            });
        });

    });

    describe('calling the search instance method without argument', function () {
        it('should return an error and no results', function () {
            this.registry.search('', function (err, results) {
                expect(err).to.not.be.null;
                expect(results).to.be.undefined;
            });
        });
    });

    //
    // clearCache
    //
    describe('called the clearCache instance method with argument', function () {

        beforeEach(function () {
            this.pkg = 'jquery';
        });

        it('should not return an error', function () {
            this.registry.clearCache(this.pkg, function (err) {
                expect(err).to.be.null;
            });
        });
    });

    describe('called the clearCache instance method without argument', function () {

        it('should not return any errors and remove all cache items', function () {
            this.registry.clearCache(function (err) {
                expect(err).to.be.null;
            });
        });
    });

});
<|endoftext|>


<commit_before>/**
* @author Saeid Mohadjer <info@saeidmohadjer.com>
* @link https://github.com/smohadjer/jquery.sameHeight
* @license http://opensource.org/licenses/MIT
*
* @version 0.0.1
*
* based on: http://jqueryboilerplate.com/
*/

;(function ($, window, document, undefined) {
	'use strict';

	var pluginName = 'sameHeight',
		defaults = {};

	//private method
	var getHeightOfTallest = function(elms) {
		var height = 0;

		$.each(elms, function() {
			var _h = $(this).outerHeight();

			if (_h > height) {
				height = _h;
			}
		});

		return height;
	};

	// The actual plugin constructor
	function Plugin(element, options) {
		this.$element = $(element);
		this.options = $.extend({}, defaults, options);
		this.init();
	}

	// methods
	var methods = {
		init: function() {
			var self = this;

			self.$elms = self.$element.children();

			$(window).on('resize', function() {
				self.setMinHeight();
			});

			self.setMinHeight();
		},

		setMinHeight: function(){
			var self = this;

			self.$elms.css({
				'min-height': ''
			});

			$.each(getRows(), function() {
				var row = this;

				//if there are more than one element in a row, set those elements
				//to same height as tallets one
				var minHeight = row.elms.length > 1 ? getHeightOfTallest(row.elms) : '';
				$(row.elms).css({
					'min-height': minHeight
				});
			});

			//returns an array of objects containing elements in the same row
			function getRows() {
				var rows = [];

				self.$elms.each(function() {
					var elm = this;
					var top = $(elm).position().top;
					var rowFound = false;

					//if rows array has a row object for current element add element
					//to that row object's elms array
					if (rows.length > 0) {
						$.each(rows, function() {
							var row = this;

							if (row.top === top) {
								row.elms.push(elm);
								rowFound = true;
								return false;
							}
						});
					}

					//if there is no row for current element in rows array add a
					//new row object to rows array
					if (!rowFound) {
						var row = {};
						row.top = top;
						row.elms = [];
						row.elms.push(elm);
						rows.push(row);
					}
				});

				return rows;
			}
		}
	};

	// build
	$.extend(Plugin.prototype, methods);

	// A really lightweight plugin wrapper around the constructor,
	// preventing against multiple instantiations
	$.fn[pluginName] = function(options) {
		this.each(function() {
			if(!$.data(this, 'plugin_' + pluginName)) {
				$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
			}
		});

		return this;
	};

})(jQuery, window, document);
<commit_msg>bug fix<commit_after>/**
* @author Saeid Mohadjer <info@saeidmohadjer.com>
* @link https://github.com/smohadjer/jquery.sameHeight
* @license http://opensource.org/licenses/MIT
*
* @version 0.0.2
*
* based on: http://jqueryboilerplate.com/
*/

;(function ($, window, document, undefined) {
	'use strict';

	var pluginName = 'sameHeight',
		defaults = {};

	//private method
	var getHeightOfTallest = function(elms) {
		var height = 0;

		$.each(elms, function() {
			var _h = $(this).outerHeight();

			if (_h > height) {
				height = _h;
			}
		});

		return height;
	};

	// The actual plugin constructor
	function Plugin(element, options) {
		this.$element = $(element);
		this.options = $.extend({}, defaults, options);
		this.init();
	}

	// methods
	var methods = {
		init: function() {
			var self = this;

			self.$elms = self.$element.children();

			$(window).on('resize', function() {
				self.setMinHeight();
			});

			//use setTimeout to make sure any code in stack is executed before
			//calculating height
			setTimeout(function() {
				self.setMinHeight();
			}, 0);
		},

		setMinHeight: function(){
			var self = this;

			self.$elms.css({
				'min-height': ''
			});

			$.each(getRows(), function() {
				var row = this;

				//if there are more than one element in a row, set those elements
				//to same height as tallets one
				var minHeight = row.elms.length > 1 ? getHeightOfTallest(row.elms) : '';
				$(row.elms).css({
					'min-height': minHeight
				});
			});

			//returns an array of objects containing elements in the same row
			function getRows() {
				var rows = [];

				self.$elms.each(function() {
					var elm = this;
					var top = $(elm).position().top;
					var rowFound = false;

					//if rows array has a row object for current element add element
					//to that row object's elms array
					if (rows.length > 0) {
						$.each(rows, function() {
							var row = this;

							if (row.top === top) {
								row.elms.push(elm);
								rowFound = true;
								return false;
							}
						});
					}

					//if there is no row for current element in rows array add a
					//new row object to rows array
					if (!rowFound) {
						var row = {};
						row.top = top;
						row.elms = [];
						row.elms.push(elm);
						rows.push(row);
					}
				});

				return rows;
			}
		}
	};

	// build
	$.extend(Plugin.prototype, methods);

	// A really lightweight plugin wrapper around the constructor,
	// preventing against multiple instantiations
	$.fn[pluginName] = function(options) {
		this.each(function() {
			if(!$.data(this, 'plugin_' + pluginName)) {
				$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
			}
		});

		return this;
	};

})(jQuery, window, document);
<|endoftext|>


<commit_before>ig.module(
  'game.entities.bam'
).requires(
  'impact.entity'
  , 'game.entities.score'
).defines(function() {
EntityBam = ig.Entity.extend({
  size: {x: 18, y:18}
  , animSheet: new ig.AnimationSheet('media/bam.png', 18, 18)
  , gravityFactor: 0
  , checkAgainst: ig.Entity.TYPE.B
  , processed: false
  , damage: 1
  , points: 1

  , init: function(x, y, settings) {
    this.parent(x, y, settings);

    this.addAnim('idle', 1, [0]);
  }

  , update: function() {
    // We need to skip our first update
    // so check() has a chance to run
    if (!this.processed) {
      this.parent();
      this.processed = true;
      return;
    }

    this.smashTile();
    this.kill();
    this.parent();
  }

  , check: function(other) {
    other.receiveDamage(this.damage);
  }

  , smashTile: function() {
    var map = ig.game.buildingMap;
    var collisionMap = ig.game.collisionMap;
    var x = this.pos.x;
    var y = this.pos.y;
    var currentTile = map.getTile(x, y);
    var currentCollision = collisionMap.getTile(x, y);
    var tile = currentTile;

    // Don't change air or end tiles
    if (currentTile === 0 || this.isEndTile(currentTile)) {
			return;
		}

		// Damnage the wall!
    currentTile += 1;

    // did we turn it into an endTile?
    if (this.isEndTile(currentTile)) {
      // Add a standable platform
      collisionMap.setTile(x, y+64, 12);
      // Points for mass distruction!
      ig.game.spawnEntity(EntityScore, x, y, {
        points: this.points
      });
    }

    map.setTile(x, y, currentTile);
  }

  , isEndTile: function(tileId) {
    return (tileId % 5) === 0;
  }
});
});<commit_msg>adding broken window random people<commit_after>ig.module(
  'game.entities.bam'
).requires(
  'impact.entity'
  , 'game.entities.score'
  , 'game.entities.windowHuman'
).defines(function() {
EntityBam = ig.Entity.extend({
  size: {x: 18, y:18}
  , animSheet: new ig.AnimationSheet('media/bam.png', 18, 18)
  , gravityFactor: 0
  , checkAgainst: ig.Entity.TYPE.B
  , processed: false
  , damage: 1
  , points: 1

  , init: function(x, y, settings) {
    this.parent(x, y, settings);

    this.addAnim('idle', 1, [0]);
  }

  , update: function() {
    // We need to skip our first update
    // so check() has a chance to run
    if (!this.processed) {
      this.parent();
      this.processed = true;
      return;
    }

    this.smashTile();
    this.kill();
    this.parent();
  }

  , check: function(other) {
    other.receiveDamage(this.damage);
  }

  , smashTile: function() {
    var map = ig.game.buildingMap;
    var collisionMap = ig.game.collisionMap;
    var x = this.pos.x;
    var y = this.pos.y;
    var currentTile = map.getTile(x, y);
    var currentCollision = collisionMap.getTile(x, y);
    var tile = currentTile;

    // Don't change air or end tiles
    if (currentTile === 0 || this.isEndTile(currentTile)) {
			return;
		}

		// Damnage the wall!
    currentTile += 1;
    console.log('tile', currentTile);

    // People can come out of broken windows
		if (this.isBrokenWindow(currentTile)) {
      ig.game.spawnEntity(EntityWindowHuman, x, y);
    }

    // did we turn it into an endTile?
    if (this.isEndTile(currentTile)) {
      // Add a standable platform
      collisionMap.setTile(x, y+64, 12);
      // Points for mass distruction!
      ig.game.spawnEntity(EntityScore, x, y, {
        points: this.points
      });
    }

    map.setTile(x, y, currentTile);
  }

  , isEndTile: function(tileId) {
    return (tileId % 5) === 0;
  }

  , isBrokenWindow: function(tileId) {
    var brokenWindowIds = [13, 14];

    return _.contains(brokenWindowIds, tileId);
  }
});
});<|endoftext|>


<commit_before>const
    Matrix = require('../index.js').Matrix;
    should = require('should');

describe('Matrix', function() {
  var mat;

  it('#Matrix() should be a function', function() {
    Matrix.should.be.a.Function;
  });

  it('should throw error when tried creating matrix without rows and columns arguments', function() {
    (function() { new Matrix(); }).should.throw();
    (function() { new Matrix(1); }).should.throw();
    (function() { new Matrix(1, 2); }).should.not.throw();
  });

  it('should be invoked with arguments rows and columns and return an object', function() {
    Matrix(1,2).should.be.an.Object;
    (new Matrix(3, 4)).should.be.an.Object;
  });

  it('#Matrix(3, 2) should return the matrix of size 3x2', function() {
    mat = Matrix(3, 2);
    mat.rows().should.equal(3);
    mat.cols().should.equal(2);
  })
});
<commit_msg>test: test Matrix methods 'set()' and 'get()'<commit_after>const
    Matrix = require('../index.js').Matrix;
    should = require('should');

describe('Matrix', function() {
  var mat;

  it('#Matrix() should be a function', function() {
    Matrix.should.be.a.Function;
  });

  it('should throw error when tried creating matrix without rows and columns arguments', function() {
    (function() { new Matrix(); }).should.throw();
    (function() { new Matrix(1); }).should.throw();
    (function() { new Matrix(1, 2); }).should.not.throw();
  });

  it('should be invoked with arguments rows and columns and return an object', function() {
    Matrix(1,2).should.be.an.Object;
    (new Matrix(3, 4)).should.be.an.Object;
  });

  it('#Matrix(3, 2) should return the matrix of size 3x2', function() {
    mat = Matrix(3, 2);
    mat.rows().should.equal(3);
    mat.cols().should.equal(2);
  })

  beforeEach(function() {
    mat = Matrix(3, 3);
    mat.set(0, 0, 1);
    mat.set(0, 1, 2);
    mat.set(0, 2, 3);
    mat.set(1, 0, 4);
    mat.set(1, 1, 5);
    mat.set(1, 2, 6);
    mat.set(2, 0, 7);
    mat.set(2, 1, 8);
    mat.set(2, 2, 9);
  });

  it('#get() should return the element value of Matrix', function() {
    mat.get(0, 0).should.equal(1);
    mat.get(0, 1).should.equal(2);
    mat.get(0, 2).should.equal(3);
    mat.get(1, 0).should.equal(4);
    mat.get(1, 1).should.equal(5);
    mat.get(1, 2).should.equal(6);
    mat.get(2, 0).should.equal(7);
    mat.get(2, 1).should.equal(8);
    mat.get(2, 2).should.equal(9);
    mat.get().should.equal("1 2 3\n4 5 6\n7 8 9");
  })
});
<|endoftext|>


<commit_before>////
//// An all-encompassing UI object.
////

// An experimental dynamic UI builder.
// TODO: will also probably need to take go_meta at some point.
function GOlrUIBeta(in_args){

    var gui_anchor = this;

    // Per-manager logger.
    var logger = new bbop.logger();
    logger.DEBUG = true;
    function ll(str){ logger.kvetch(str); }

    // There should be a string interface_id argument.
    if( in_args && ! in_args['interface_id'] ){
	ll('GUI: ERROR: no interface_id argument');
	if( typeof in_args['interface_id'] != 'string' ){
	    ll('GUI: ERROR: no interface_id string argument');
	}
    }
    // The location where we'll build and manage the interface.
    this.interface_id = in_args['interface_id'];

    // AmiGO helper.
    var amigo = new bbop.amigo();
    var golr = amigo.golr_response;

    // Get the user interface hook.
    //var ui_div_hook = golr.parameter(json_data, 'interface_id');
    var ui_div_hook = this.interface_id;
    // Mangle everything around this unique id so we don't collide
    // with other instances on the same page.
    var mangle = ui_div_hook + '_ui_element_';
    // ...
    var accordion_div_hook = mangle + 'filter-accordion';

    // Initialze with reseting data.
    this.init = function(json_data){

	ll('UIB: Build UI from reset response: ' + ui_div_hook);

	// First, remove anything that was there.
	jQuery('#' + ui_div_hook).empty();

	// Start building the accordion here.
	var filter_accordion_attrs = {
	    id: accordion_div_hook,
	    style: 'width: 25em;'
	};
	var filter_accordion =
	    new bbop.html.accordion([], filter_accordion_attrs);

	//var field_attr_hash = {};
	var field_list = golr.facet_field_list(json_data);
	function _look_at_fields(in_field, in_i){
	    //ll('GUI: saw field: ' + in_field);

	    // Create ul lists of the facet contents.
	    var facet_list_ul_attrs = {
		id: mangle + 'filter-list-' + in_field,
		'class': 'golr-filter-selectable',
		style: 'height: 30em;'
	    };
	    var facet_list_ul = new bbop.html.list([], facet_list_ul_attrs);
	    var facet_contents_list = golr.facet_field(json_data, in_field);
	    bbop.core.each(facet_contents_list,
			   function(item, i){
			       var name = item[0];
			       var count = item[1];
			       //ll('GUI: saw facet item: ' + name);
			       facet_list_ul.add_child(name);
			   });

	    // Add the ul list to the accordion.
	    //ll('GUI: out');
	    //ll('GUI: add to accordion: ' + facet_list_ul.output());
	    //ll('GUI: passed');
	    filter_accordion.add_child(in_field, facet_list_ul);
	}
	bbop.core.each(field_list, _look_at_fields);

	// TODO: Add the output from the accordion to the page.
	jQuery('#' + ui_div_hook).html(filter_accordion.output());

	// // TODO
	// var query_text =
	// 	widgets.form.text_input('q', 'q', 25,
	// 				'Search for
');

	jQuery(function() {
		   // Add the jQuery accordioning.
		   jQuery("#" + mangle +
			  "filter-accordion").accordion({ clearStyle: true,
							  collapsible: true,
							  active: false });

		   // Add the jQuery selectableing. When any selecting
		   // activity is stopped, grab all items from the
		   // entire interface and create a filtering object.
		   function _init_lambda(item, i){
		       var _select_arg = {
			   stop: function(){
			       // var result = jQuery("#DEBUG").empty();
			       // result.append("result");
			       // jQuery(".ui-selected", this).each(
			       // 	   function(){
			       //    var liid = mangle +"filter-list-"+ item;
			       // 	       var index =
			       //   jQuery("#"+ liid +" li").index(this);
			       // 	       result.append(" " + item + " " +
			       // 			     ( index + 1));
			       // 	   });
			       gui_anchor.check_status();
			   }};
		       ll('GUI examining: ' + item);
		       jQuery("#" + mangle +
			      "filter-list-" + item).selectable(_select_arg);
		   }
		   bbop.core.each(field_list, _init_lambda);
	       });
    };

    // Return a query object?
    // TODO: Eventually call anything that registered for GUI events.
    this.check_status = function(){

	ll('UIB: Build UI from reset response: ' + ui_div_hook);

	// DEBUG: First, remove anything that was there.
	var result = jQuery("#DEBUG").empty();

	// Figure out where our filters are and what they are.
	ll('UIB: Scanning filter accordion: ' + accordion_div_hook);
	jQuery(".golr-filter-selectable .ui-selected").each(
	    function(){
		// Filter set in question. Subtract the head from the
		// id to get the original mangled filter set.
		var filter_set_id_head = mangle + "filter-list-";
		var filter_set_id = jQuery(this).parent().attr('id');
		var filter_set =
		    filter_set_id.substring(filter_set_id_head.length,
					    filter_set_id.length);

		// Actual item.
		var filter_item = jQuery(this).html();

		// Debug.
		result.append(" " + filter_set + " " + filter_item);
	    });

	// NOTE: the first item in the hash is the default op.
	// TODO: need a special object for adding and translations
	//       would be easy for testing!

	// TODO: Callbacks.
    };
}
<commit_msg>bugfixes; tests; some login<commit_after>////
//// An all-encompassing UI object.
////

// An experimental dynamic UI builder.
// TODO: will also probably need to take go_meta at some point.
function GOlrUIBeta(in_args){

    var gui_anchor = this;

    // Per-manager logger.
    var logger = new bbop.logger();
    logger.DEBUG = true;
    function ll(str){ logger.kvetch(str); }

    // There should be a string interface_id argument.
    if( in_args && ! in_args['interface_id'] ){
	ll('GUI: ERROR: no interface_id argument');
	if( typeof in_args['interface_id'] != 'string' ){
	    ll('GUI: ERROR: no interface_id string argument');
	}
    }
    // The location where we'll build and manage the interface.
    this.interface_id = in_args['interface_id'];

    // AmiGO helper.
    var amigo = new bbop.amigo();
    var golr = amigo.golr_response;

    // Get the user interface hook.
    //var ui_div_hook = golr.parameter(json_data, 'interface_id');
    var ui_div_hook = this.interface_id;
    // Mangle everything around this unique id so we don't collide
    // with other instances on the same page.
    var mangle = ui_div_hook + '_ui_element_';
    // ...
    var accordion_div_hook = mangle + 'filter-accordion';

    // Initialze with reseting data.
    this.init = function(json_data){

	ll('UIB: Build UI from reset response: ' + ui_div_hook);

	// First, remove anything that was there.
	jQuery('#' + ui_div_hook).empty();

	// Start building the accordion here.
	var filter_accordion_attrs = {
	    id: accordion_div_hook,
	    style: 'width: 25em;'
	};
	var filter_accordion =
	    new bbop.html.accordion([], filter_accordion_attrs);

	//var field_attr_hash = {};
	var field_list = golr.facet_field_list(json_data);
	function _look_at_fields(in_field, in_i){
	    //ll('GUI: saw field: ' + in_field);

	    // Create ul lists of the facet contents.
	    var facet_list_ul_attrs = {
		id: mangle + 'filter-list-' + in_field,
		'class': 'golr-filter-selectable',
		style: 'height: 30em;'
	    };
	    var facet_list_ul = new bbop.html.list([], facet_list_ul_attrs);
	    var facet_contents_list = golr.facet_field(json_data, in_field);
	    bbop.core.each(facet_contents_list,
			   function(item, i){
			       var name = item[0];
			       var count = item[1];
			       //ll('GUI: saw facet item: ' + name);
			       facet_list_ul.add_child(name);
			   });

	    // Add the ul list to the accordion.
	    //ll('GUI: out');
	    //ll('GUI: add to accordion: ' + facet_list_ul.to_string());
	    //ll('GUI: passed');
	    filter_accordion.add_child(in_field, facet_list_ul);
	}
	bbop.core.each(field_list, _look_at_fields);

	// TODO: Add the output from the accordion to the page.
	jQuery('#' + ui_div_hook).html(filter_accordion.to_string());

	// // TODO
	// var query_text =
	// 	widgets.form.text_input('q', 'q', 25,
	// 				'Search for
');

	jQuery(function() {
		   // Add the jQuery accordioning.
		   jQuery("#" + mangle +
			  "filter-accordion").accordion({ clearStyle: true,
							  collapsible: true,
							  active: false });

		   // Add the jQuery selectableing. When any selecting
		   // activity is stopped, grab all items from the
		   // entire interface and create a filtering object.
		   function _init_lambda(item, i){
		       var _select_arg = {
			   stop: function(){
			       // var result = jQuery("#DEBUG").empty();
			       // result.append("result");
			       // jQuery(".ui-selected", this).each(
			       // 	   function(){
			       //    var liid = mangle +"filter-list-"+ item;
			       // 	       var index =
			       //   jQuery("#"+ liid +" li").index(this);
			       // 	       result.append(" " + item + " " +
			       // 			     ( index + 1));
			       // 	   });
			       gui_anchor.check_status();
			   }};
		       ll('GUI examining: ' + item);
		       jQuery("#" + mangle +
			      "filter-list-" + item).selectable(_select_arg);
		   }
		   bbop.core.each(field_list, _init_lambda);
	       });
    };

    // Return a query object?
    // TODO: Eventually call anything that registered for GUI events.
    this.check_status = function(){

	ll('UIB: Build UI from reset response: ' + ui_div_hook);

	// DEBUG: First, remove anything that was there.
	var result = jQuery("#DEBUG").empty();

	// Figure out where our filters are and what they are.
	ll('UIB: Scanning filter accordion: ' + accordion_div_hook);
	jQuery(".golr-filter-selectable .ui-selected").each(
	    function(){
		// Filter set in question. Subtract the head from the
		// id to get the original mangled filter set.
		var filter_set_id_head = mangle + "filter-list-";
		var filter_set_id = jQuery(this).parent().attr('id');
		var filter_set =
		    filter_set_id.substring(filter_set_id_head.length,
					    filter_set_id.length);

		// Actual item.
		var filter_item = jQuery(this).html();

		// Debug.
		result.append(" " + filter_set + " " + filter_item);
	    });

	// NOTE: the first item in the hash is the default op.
	// TODO: need a special object for adding and translations
	//       would be easy for testing!

	// TODO: Callbacks.
    };
}
<|endoftext|>


<commit_before>import { morph } from './utils'

export const collapsibleSteps = false

const celsiusUnits = {
    metric: {
        label: '°C',
        convert: value => (value - 32) / 1.8,  // Convert to celsius
        convertTransfer: value => value / 1.8,  // Convert difference to celsuis
        precision: 1,
        transferPrecision: 2
    },
    imperial: {
        label: '°F',
        convert: value => value * 1.8 + 32,  // Convert to fahrenheit
        convertTransfer: value => value * 1.8, // Convert difference to fahrenheit
        precision: 1,
        transferPrecision: 2
    }
}

const mmUnits = {
    metric: {
        label: 'mm',
        convert: value => value * 25.4, // Convert to millimeters
        precision: 0,
        transferPrecision: 0
    },
    imperial: {
        label: 'in',
        convert: value => value / 25.4, // Convert to inches
        precision: 1,
        transferPrecision: 1
    }
}

const daysUnits = {
    metric: {
        label: 'days',
        convert: value => value,
        precision: 0,
        transferPrecision: 0
    },
    imperial: {
        label: 'days',
        convert: value => value,
        precision: 0,
        transferPrecision: 0
    }
}

const degreeDaysUnits = {
    metric: {
        label: 'dd',
        convert: value => value,
        precision: 0,
        transferPrecision: 0
    },
    imperial: {
        label: 'dd',
        convert: value => value,
        precision: 0,
        transferPrecision: 0
    }
}

const heatMoistureUnits = {
    metric: {
        label: '',
        convert: value => value,
        precision: 1,
        transferPrecision: 1
    },
    imperial: {
        label: '',
        convert: value => value,
        precision: 1,
        transferPrecision: 1
    }
}

export const variables = [
    {
        name: 'MAT',
        label: 'Mean annual temperature',
        multiplier: 10,
        units: celsiusUnits,
    },
    {
        name: 'MWMT',
        label: 'Mean warmest month temperature',
        multiplier: 10,
        units: celsiusUnits,
    },
    {
        name: 'MCMT',
        label: 'Mean coldest month temperature',
        multiplier: 10,
        units: celsiusUnits,
    },
    {
        name: 'TD',
        label: 'Temperature difference between MWMT and MCMT, or continentality',
        multiplier: 10,
        units: {
            metric: {
                label: '°C',
                convert: value => value / 1.8,  // Convert temp difference to C
                precision: 1,
                transferPrecision: 2
            },
            imperial: {
                label: '°F',
                convert: value => value * 1.8, // Convert temp difference to F
                precision: 1,
                transferPrecision: 2
            }
        }
    },
    {
        name: 'MAP',
        label: 'Mean annual precipitation',
        multiplier: 1,
        units: mmUnits
    },
    {
        name: 'MSP',
        label: 'Mean summer precipitation, May to September',
        multiplier: 1,
        units: mmUnits
    },
    {
        name: 'AHM',
        label: 'Annual heat-moisture index',
        multiplier: 10,
        units: heatMoistureUnits
    },
    {
        name: 'SHM',
        label: 'Summer heat-moisture index',
        multiplier: 10,
        units: heatMoistureUnits
    },
    {
        name: 'DD_0',
        label: 'Degree-days below 0°C',
        multiplier: 1,
        units: degreeDaysUnits
    },
    {
        name: 'DD5',
        label: 'Degree-days above 5°C',
        multiplier: 1,
        units: degreeDaysUnits
    },
    {
        name: 'FFP',
        label: 'Frost-free period',
        multiplier: 1,
        units: daysUnits
    },
    {
        name: 'PAS',
        label: 'Precipitation as snow, August to July',
        multiplier: 1,
        units: mmUnits
    },
    {
        name: 'EMT',
        label: 'Extreme minimum temperature over 30 years',
        multiplier: 10,
        units: celsiusUnits
    },
    {
        name: 'EXT',
        label: 'Extreme maximum temperature over 30 years',
        multiplier: 10,
        units: celsiusUnits
    },
    {
        name: 'Eref',
        label: 'Hargreaves reference evaporation',
        multiplier: 1,
        units: mmUnits
    },
    {
        name: 'CMD',
        label: 'Hargreaves climatic moisture deficit',
        multiplier: 1,
        units: mmUnits
    }
];

export const species = [
    {
        name: 'psme',
        label: 'Douglas-fir',
        transfers: {
            MAT: 20,
            MWMT: 20,
            MCMT: 20,
            TD: 20,
            EMT: 20,
            EXT: 20,
            MAP: 200,
            MSP: 50,
            FFP: 20,
            AHM: 30,
            SHM: 20
        }
    },
    {
        name: 'pico',
        label: 'Lodgepole pine',
        transfers: {
            MAT: 20,
            MWMT: 20,
            MCMT: 20,
            TD: 20,
            EMT: 20,
            EXT: 20,
            MAP: 200,
            MSP: 50,
            FFP: 20,
            AHM: 30,
            SHM: 20
        }
    },
    {
        name: 'piba',
        label: 'Jack pine'
    },
    {
        name: 'pipo',
        label: 'Ponderosa pine',
        transfers: {
            MAT: 25,
            MWMT: 25,
            MCMT: 25,
            TD: 25,
            EMT: 25,
            EXT: 25,
            MAP: 200,
            MSP: 50,
            FFP: 30,
            AHM: 30,
            SHM: 20
        }
    },
    {
        name: 'pima',
        label: 'Black spruce'
    },
    {
        name: 'thpl',
        label: 'Western red cedar',
        transfers: {
            MAT: 30,
            MWMT: 30,
            MCMT: 30,
            TD: 30,
            EMT: 30,
            EXT: 30,
            MAP: 200,
            MSP: 50,
            FFP: 50,
            AHM: 30,
            SHM: 20
        }
    },
    {
        name: 'pimo',
        label: 'Western white pine',
        transfers: {
            MAT: 30,
            MWMT: 30,
            MCMT: 30,
            TD: 30,
            EMT: 30,
            EXT: 30,
            MAP: 200,
            MSP: 50,
            FFP: 50,
            AHM: 30,
            SHM: 20
        }
    }
]

export const constraints = {
    elevation: {
        values: {
            range: 0
        },
        serialize: (configuration, values) => {
            let { elevation } = configuration.point
            let { range } = values

            return {min: elevation - range, max: elevation + range}
        }
    },
    photoperiod: {
        values: {
            hours: 0,
            month: 1,
            day: 1,
            year: 1961
        },
        serialize: (configuration, values) => {
            let { x, y } = configuration.point
            return morph(values, {lon: x, lat: y})
        }
    },
    latitude: {
        values: {
            range: 0
        },
        serialize: (configuration, { range }) => {
            let { y } = configuration.point
            return {min: y - range, max: y + range}
        }
    },
    longitude: {
        values: {
            range: 0
        },
        serialize: (configuration, { range }) => {
            let { x } = configuration.point
            return {min: x - range, max: x + range}
        }
    },
    distance: {
        values: {
            range: 0
        },
        serialize: (configuration, { range }) => {
            let { x, y } = configuration.point
            return { lat: y, lon: x, distance: range}
        }
    },
    shapefile: {
        values: {
            geoJSON: null,
            filename: null
        },
        serialize: (configuration, { geoJSON }) => {
            return { geoJSON }
        }
    }
}

export const timeLabels = {
    '1961_1990': '1961 - 1990',
    '1981_2010': '1981 - 2010',
    '2025rcp45': '2025 RCP 4.5',
    '2025rcp85': '2025 RCP 8.5',
    '2055rcp45': '2055 RCP 4.5',
    '2055rcp85': '2055 RCP 8.5',
    '2085rcp45': '2085 RCP 4.5',
    '2085rcp85': '2085 RCP 8.5'
}

export const regions = [
    {
        name: 'ak2',
        label: 'Alaska'
    },
    {
        name: 'west2',
        label: 'Western US'
    },
    {
        name: 'nc1',
        label: 'North Central'
    },
    {
        name: 'uscentral1',
        label: 'Central US'
    },
    {
        name: 'ne1',
        label: 'North East'
    },
    {
        name: 'useast1',
        label: "Eastern US"
    }
]

export const regionsBoundariesUrl = '/static/geometry/regions.topojson'

export const reports = [
    {
        name: 'pdf',
        label: 'PDF',
        url: '/sst/create-pdf/'
    },
    {
        name: 'pptx',
        label: 'PPT',
        url: '/sst/create-ppt/'
    }
]

<commit_msg>Use `apiRoot` for report URLs<commit_after>import { morph } from './utils'
import config from 'seedsource/config'

let { apiRoot } = config

export const collapsibleSteps = false

const celsiusUnits = {
    metric: {
        label: '°C',
        convert: value => (value - 32) / 1.8,  // Convert to celsius
        convertTransfer: value => value / 1.8,  // Convert difference to celsuis
        precision: 1,
        transferPrecision: 2
    },
    imperial: {
        label: '°F',
        convert: value => value * 1.8 + 32,  // Convert to fahrenheit
        convertTransfer: value => value * 1.8, // Convert difference to fahrenheit
        precision: 1,
        transferPrecision: 2
    }
}

const mmUnits = {
    metric: {
        label: 'mm',
        convert: value => value * 25.4, // Convert to millimeters
        precision: 0,
        transferPrecision: 0
    },
    imperial: {
        label: 'in',
        convert: value => value / 25.4, // Convert to inches
        precision: 1,
        transferPrecision: 1
    }
}

const daysUnits = {
    metric: {
        label: 'days',
        convert: value => value,
        precision: 0,
        transferPrecision: 0
    },
    imperial: {
        label: 'days',
        convert: value => value,
        precision: 0,
        transferPrecision: 0
    }
}

const degreeDaysUnits = {
    metric: {
        label: 'dd',
        convert: value => value,
        precision: 0,
        transferPrecision: 0
    },
    imperial: {
        label: 'dd',
        convert: value => value,
        precision: 0,
        transferPrecision: 0
    }
}

const heatMoistureUnits = {
    metric: {
        label: '',
        convert: value => value,
        precision: 1,
        transferPrecision: 1
    },
    imperial: {
        label: '',
        convert: value => value,
        precision: 1,
        transferPrecision: 1
    }
}

export const variables = [
    {
        name: 'MAT',
        label: 'Mean annual temperature',
        multiplier: 10,
        units: celsiusUnits,
    },
    {
        name: 'MWMT',
        label: 'Mean warmest month temperature',
        multiplier: 10,
        units: celsiusUnits,
    },
    {
        name: 'MCMT',
        label: 'Mean coldest month temperature',
        multiplier: 10,
        units: celsiusUnits,
    },
    {
        name: 'TD',
        label: 'Temperature difference between MWMT and MCMT, or continentality',
        multiplier: 10,
        units: {
            metric: {
                label: '°C',
                convert: value => value / 1.8,  // Convert temp difference to C
                precision: 1,
                transferPrecision: 2
            },
            imperial: {
                label: '°F',
                convert: value => value * 1.8, // Convert temp difference to F
                precision: 1,
                transferPrecision: 2
            }
        }
    },
    {
        name: 'MAP',
        label: 'Mean annual precipitation',
        multiplier: 1,
        units: mmUnits
    },
    {
        name: 'MSP',
        label: 'Mean summer precipitation, May to September',
        multiplier: 1,
        units: mmUnits
    },
    {
        name: 'AHM',
        label: 'Annual heat-moisture index',
        multiplier: 10,
        units: heatMoistureUnits
    },
    {
        name: 'SHM',
        label: 'Summer heat-moisture index',
        multiplier: 10,
        units: heatMoistureUnits
    },
    {
        name: 'DD_0',
        label: 'Degree-days below 0°C',
        multiplier: 1,
        units: degreeDaysUnits
    },
    {
        name: 'DD5',
        label: 'Degree-days above 5°C',
        multiplier: 1,
        units: degreeDaysUnits
    },
    {
        name: 'FFP',
        label: 'Frost-free period',
        multiplier: 1,
        units: daysUnits
    },
    {
        name: 'PAS',
        label: 'Precipitation as snow, August to July',
        multiplier: 1,
        units: mmUnits
    },
    {
        name: 'EMT',
        label: 'Extreme minimum temperature over 30 years',
        multiplier: 10,
        units: celsiusUnits
    },
    {
        name: 'EXT',
        label: 'Extreme maximum temperature over 30 years',
        multiplier: 10,
        units: celsiusUnits
    },
    {
        name: 'Eref',
        label: 'Hargreaves reference evaporation',
        multiplier: 1,
        units: mmUnits
    },
    {
        name: 'CMD',
        label: 'Hargreaves climatic moisture deficit',
        multiplier: 1,
        units: mmUnits
    }
];

export const species = [
    {
        name: 'psme',
        label: 'Douglas-fir',
        transfers: {
            MAT: 20,
            MWMT: 20,
            MCMT: 20,
            TD: 20,
            EMT: 20,
            EXT: 20,
            MAP: 200,
            MSP: 50,
            FFP: 20,
            AHM: 30,
            SHM: 20
        }
    },
    {
        name: 'pico',
        label: 'Lodgepole pine',
        transfers: {
            MAT: 20,
            MWMT: 20,
            MCMT: 20,
            TD: 20,
            EMT: 20,
            EXT: 20,
            MAP: 200,
            MSP: 50,
            FFP: 20,
            AHM: 30,
            SHM: 20
        }
    },
    {
        name: 'piba',
        label: 'Jack pine'
    },
    {
        name: 'pipo',
        label: 'Ponderosa pine',
        transfers: {
            MAT: 25,
            MWMT: 25,
            MCMT: 25,
            TD: 25,
            EMT: 25,
            EXT: 25,
            MAP: 200,
            MSP: 50,
            FFP: 30,
            AHM: 30,
            SHM: 20
        }
    },
    {
        name: 'pima',
        label: 'Black spruce'
    },
    {
        name: 'thpl',
        label: 'Western red cedar',
        transfers: {
            MAT: 30,
            MWMT: 30,
            MCMT: 30,
            TD: 30,
            EMT: 30,
            EXT: 30,
            MAP: 200,
            MSP: 50,
            FFP: 50,
            AHM: 30,
            SHM: 20
        }
    },
    {
        name: 'pimo',
        label: 'Western white pine',
        transfers: {
            MAT: 30,
            MWMT: 30,
            MCMT: 30,
            TD: 30,
            EMT: 30,
            EXT: 30,
            MAP: 200,
            MSP: 50,
            FFP: 50,
            AHM: 30,
            SHM: 20
        }
    }
]

export const constraints = {
    elevation: {
        values: {
            range: 0
        },
        serialize: (configuration, values) => {
            let { elevation } = configuration.point
            let { range } = values

            return {min: elevation - range, max: elevation + range}
        }
    },
    photoperiod: {
        values: {
            hours: 0,
            month: 1,
            day: 1,
            year: 1961
        },
        serialize: (configuration, values) => {
            let { x, y } = configuration.point
            return morph(values, {lon: x, lat: y})
        }
    },
    latitude: {
        values: {
            range: 0
        },
        serialize: (configuration, { range }) => {
            let { y } = configuration.point
            return {min: y - range, max: y + range}
        }
    },
    longitude: {
        values: {
            range: 0
        },
        serialize: (configuration, { range }) => {
            let { x } = configuration.point
            return {min: x - range, max: x + range}
        }
    },
    distance: {
        values: {
            range: 0
        },
        serialize: (configuration, { range }) => {
            let { x, y } = configuration.point
            return { lat: y, lon: x, distance: range}
        }
    },
    shapefile: {
        values: {
            geoJSON: null,
            filename: null
        },
        serialize: (configuration, { geoJSON }) => {
            return { geoJSON }
        }
    }
}

export const timeLabels = {
    '1961_1990': '1961 - 1990',
    '1981_2010': '1981 - 2010',
    '2025rcp45': '2025 RCP 4.5',
    '2025rcp85': '2025 RCP 8.5',
    '2055rcp45': '2055 RCP 4.5',
    '2055rcp85': '2055 RCP 8.5',
    '2085rcp45': '2085 RCP 4.5',
    '2085rcp85': '2085 RCP 8.5'
}

export const regions = [
    {
        name: 'ak2',
        label: 'Alaska'
    },
    {
        name: 'west2',
        label: 'Western US'
    },
    {
        name: 'nc1',
        label: 'North Central'
    },
    {
        name: 'uscentral1',
        label: 'Central US'
    },
    {
        name: 'ne1',
        label: 'North East'
    },
    {
        name: 'useast1',
        label: "Eastern US"
    }
]

export const regionsBoundariesUrl = '/static/geometry/regions.topojson'

export const reports = [
    {
        name: 'pdf',
        label: 'PDF',
        url: `${apiRoot}create-pdf/`
    },
    {
        name: 'pptx',
        label: 'PPT',
        url: `${apiRoot}create-ppt/`
    }
]

<|endoftext|>