<commit_before>/** @jsx React.DOM */

var Attribution = React.createClass({
  render: function() {
    return (

                   Designed by Dr. Kat

	           Made with React.js

    );
  }
});

var DataScienceTopics = React.createClass({
  render: function() {
    var schedule = ["Mining", "Algorithms", "Science", "Curation", "&", "Realtime Analytics"];
    var items = {};

    schedule.forEach(function(i) {
      items[i] =
{i}
;
    });

    return (

            {items}

    );
  }
});

/** ==================================================
*/

var RouterMixin = {
  componentWillMount : function() {
    this.callback = (function() {
      this.forceUpdate();
    }).bind(this);

    this.props.router.on("route", this.callback);
  },
  componentWillUnmount : function() {
    this.props.router.off("route", this.callback);
  }
};

var ScheduleComponent = React.createClass({
  mixins : [RouterMixin],
  handle : function() {
    this.props.router.navigate("foo", {
      trigger : true
    });
  },
  getInitialState: function() {
    return {data1: []};
  },
  componentDidMount: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      success: function(data) {
        this.setState({data1: data.items});
      }.bind(this)
    });
  },
  render : function() {
    var className = "animate-leave animate-leave-active";

    if (this.props.router.current == null ) {
      var splash= React.DOM.img({src: '/static/images/eye.jpg'}, '');
    }

    if (this.props.router.current == "schedule") {
      className = "animate-enter animate-enter-active";
      var n = this.state.data1.length;

      var scheduleTitle = React.DOM.h2({}, 'Previous Schedule');

      var c = React.DOM.span({className: 'close'}, React.DOM.a({href: '/'}, 'x') );

      var scheduleList = this.state.data1.map(function(item, i) {
          return (

                    {moment(item.date).fromNow()} - "{item.topic}"

          );
      });

    }

    return (

          {splash}
          {c}
          {scheduleTitle}

            {scheduleList}

    );
  }
});

var InterfaceComponent = React.createClass({
  mixins : [RouterMixin],
  render : function() {
    var router = this.props.router;

    return (

        <ScheduleComponent router={router} url="schedule.json"  />

    );
  }
});

var Router = Backbone.Router.extend({
  routes : {
    "schedule" : "schedule"
  },
  schedule : function() {
    this.current = "schedule";
  }
});

var router = new Router();

React.renderComponent(
  <DataScienceTopics />,
  document.getElementById('topics')
);

React.renderComponent(
  <Attribution />,
  document.getElementById('footer')
);

React.renderComponent(
  <InterfaceComponent router={router} />,
  document.getElementById('rightMain')
);

Backbone.history.start();
<commit_msg>some notes for feature improvement<commit_after>/** @jsx React.DOM */

var Attribution = React.createClass({
  render: function() {
    return (

                   Designed by Dr. Kat

	           Made with React.js

    );
  }
});

var DataScienceTopics = React.createClass({
  render: function() {
    var schedule = ["Mining", "Algorithms", "Science", "Curation", "&", "Realtime Analytics"];
    var items = {};

    schedule.forEach(function(i) {
      items[i] =
{i}
;
    });

    return (

            {items}

    );
  }
});

/** ==================================================
*/

var RouterMixin = {
  componentWillMount : function() {
    this.callback = (function() {
      this.forceUpdate();
    }).bind(this);

    this.props.router.on("route", this.callback);
  },
  componentWillUnmount : function() {
    this.props.router.off("route", this.callback);
  }
};

var FooComponent = React.createClass({
  mixins : [RouterMixin],
  handle : function() {
    this.props.router.navigate("bar", {
      trigger : true
    });
  },
  render : function() {
    var className = "animate-leave animate-leave-active";
    var displayText = "";

    if (this.props.router.current == "foo") {
      className = "animate-enter animate-enter-active";
      displayText = "in foo, go to bar";
    }

    return (

        {displayText}

    );
  }
});

var BarComponent = React.createClass({
  mixins : [RouterMixin],
  handle : function() {
    this.props.router.navigate("foo", {
      trigger : true
    });
  },
  render : function() {
    var className = "animate-leave animate-leave-active";
    var displayText = "";

    if (this.props.router.current == "bar") {
      className = "animate-enter animate-enter-active";
      displayText = "in bar, go to foo";
    }

    return (

        {displayText}

    );
  }
});

var ScheduleComponent = React.createClass({
  mixins : [RouterMixin],
  handle : function() {
    this.props.router.navigate("foo", {
      trigger : true
    });
  },
  getInitialState: function() {
    return {data1: []};
  },
  componentDidMount: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      success: function(data) {
        this.setState({data1: data.items});
      }.bind(this)
    });
  },
  render : function() {
    var className = "animate-leave animate-leave-active";

    if (this.props.router.current == null ) {
      var splash= React.DOM.img({src: '/static/images/eye.jpg'}, '');
    }

    if (this.props.router.current == "schedule") {
      className = "animate-enter animate-enter-active";
      var n = this.state.data1.length;

      var scheduleTitle = React.DOM.h2({}, 'Previous Schedule');

      var c = React.DOM.span({className: 'close'}, React.DOM.a({href: '/'}, 'x') );

      var scheduleList = this.state.data1.map(function(item, i) {
          return (

                    {moment(item.date).fromNow()} - "{item.topic}"

          );
      });

    }

    return (

          {splash}
          {c}
          {scheduleTitle}

            {scheduleList}

    );
  }
});

var InterfaceComponent = React.createClass({
  mixins : [RouterMixin],
  render : function() {
    var router = this.props.router;

    return (

        <FooComponent router={router} />
        <BarComponent router={router} />
        <ScheduleComponent router={router} url="schedule.json"  />

    );
  }
});

var Router = Backbone.Router.extend({
  routes : {
    "foo" : "foo",
    "bar" : "bar",
    "schedule" : "schedule"
  },
  foo : function() {
    this.current = "foo";
  },
  bar : function() {
    this.current = "bar";
  },
  schedule : function() {
    this.current = "schedule";
  }
});

var router = new Router();

React.renderComponent(
  <DataScienceTopics />,
  document.getElementById('topics')
);

React.renderComponent(
  <Attribution />,
  document.getElementById('footer')
);

// Add an if condition for if it exists
React.renderComponent(
  <InterfaceComponent router={router} />,
  document.getElementById('rightMain')
);

Backbone.history.start();
<|endoftext|>


<commit_before>import $ from 'jquery';
import is from 'is_js';
import { getEmojiByName } from '../../data/emojis';
import sanitizeHtml from 'sanitize-html';
import twemoji from 'twemoji';
import app from '../../app';
import BaseModel from '../BaseModel';

/**
 * Will return a processed chat messages with changes appropriate for the UI (e.g. emojis will be
 * twemojified, ob urls will be turned into links, etc...).
 */
export function processMessage(message) {
  if (typeof message !== 'string') {
    throw new Error('Please provide a message as a string.');
  }

  let processedMessage = message;

  // jquery's html function converts &'s to &amps which messes with some of our
  // string replacements, particulary when the &amps are in an ob link. So, we'll
  // replace them with something else and then replace them back later.
  processedMessage = processedMessage.replace(/&/g, '__ob-full-amp__')
    .replace(/&/g, '__ob-compact-amp__');

  let $message = $(`<div>${processedMessage}</div>`);
  const anchors = [];

  // Ensure any OB links, handles (must be @ prefaced) or GUIDS are turned into anchor tags.

  // First we'll pull out any existing anchors and set them aside since we want to
  // leave those alone (i.e. avoid wrapping a guid / handle that's already in an anchor in
  // another one).
  $message.find('a')
    .each((index, el) => {
      anchors.push(el);
      $(el).replaceWith($('<div />').addClass('__ob-replaced-anchor__'));
    });

  const wordsToAnchorify = [];
  const findWords = node => {
    if (node.nodeType === 3) {
      // It's a text node. Loop through each word and if it's a guid or handle we keep track of it
      // so later we'll wrap it in an anchor element.
      node.textContent.replace(/\r\n/g, ' ')
        .replace('\n', ' ')
        .match(/\S+\s*/g)
        .forEach(word => {
          const w = word.trim();
          if (wordsToAnchorify.includes(w)) return;

          if ((w.startsWith('@') && w.length > 1) ||
            (w.startsWith('ob://') && w.length > 5) ||
            (w.startsWith('http://') && w.length >= 11) ||
            (w.startsWith('https://') && w.length >= 12) ||
            (w.startsWith('www.') && w.length >= 8)) {
            wordsToAnchorify.push(w);
          }
        });
    } else {
      node.childNodes.forEach(child => findWords(child));
    }
  };

  findWords($message[0]);

  processedMessage = $message.html();

  wordsToAnchorify.forEach(word => {
    let href = !is.url(word) && !word.startsWith('ob://') ?
      `#ob://${word}` : word;

    if (is.url(word)) {
      const link = document.createElement('a');
      link.setAttribute('href', word);
      if (link.protocol === 'file:') {
        href = `http://${word}`;
      }
    }

    processedMessage = processedMessage
      .split(word)
      .join(`<a href="${href}" class="clrTEm">${word}</a>`);
  });

  // restore the anchors we pulled out earlier
  $message = $(`<div>${processedMessage}</div>`);
  $message.find('.__ob-replaced-anchor__')
    .each((index, el) => {
      $(el).replaceWith($(anchors[index]).addClass('clrTEm'));
    });

  processedMessage = $message.html()
    .replace(/__ob-full-amp__/g, '&')
    .replace(/__ob-compact-amp__/g, '&');

  // convert any unicode emoji characters to images via Twemoji
  processedMessage = twemoji.parse(processedMessage,
    icon => (`../imgs/emojis/72X72/${icon}.png`));

  return processedMessage;
}

export default class ChatMessage extends BaseModel {
  defaults() {
    return {
      subject: '',
      message: '',
      read: false,
      outgoing: true,
    };
  }

  get idAttribute() {
    return 'messageId';
  }

  get isGroupChatMessage() {
    return !!this.get('peerIds');
  }

  static get max() {
    return {
      subjectLength: 500,
      messageLength: 20000,
    };
  }

  url() {
    return app.getServerUrl(`ob/${this.isGroupChatMessage ? 'groupchat' : 'chat'}/`);
  }

  set(key, val, options = {}) {
    // Handle both `"key", value` and `{key: value}` -style arguments.
    let attrs;
    let opts = options;

    if (typeof key === 'object') {
      attrs = key;
      opts = val || {};
    } else {
      (attrs = {})[key] = val;
    }

    if (typeof attrs.message === 'string') {
      // Convert any emoji placeholder (e.g :smiling_face:) into
      // emoji unicode characters.
      const emojiPlaceholderRegEx = new RegExp(':.+?:', 'g');
      const matches = attrs.message.match(emojiPlaceholderRegEx, 'g');

      if (matches) {
        matches.forEach(match => {
          const emoji = getEmojiByName(match);

          if (emoji && emoji.char) {
            attrs.message = attrs.message.replace(match, emoji.char);
          }
        });
      }

      // sanitize the message
      attrs.message = sanitizeHtml(attrs.message);

      // Generate a processed message with changes to the message that are specific to our UI.
      attrs.processedMessage = processMessage(attrs.message);
    } else {
      // The processedMessage is automatically derived from the message and should not
      // be set directly.
      delete attrs.processedMessage;
    }

    return super.set(attrs, opts);
  }

  validate(attrs) {
    const errObj = {};
    const addError = (fieldName, error) => {
      errObj[fieldName] = errObj[fieldName] || [];
      errObj[fieldName].push(error);
    };

    const max = this.constructor.max;

    if (!this.isGroupChatMessage) {
      if (!attrs.peerId) {
        addError('peerId', 'The peerId is required');
      }
    } else if (!Array.isArray(attrs.peerIds) || !attrs.peerIds.length) {
      addError('peerIds', 'peerIds must be provided as an array.');
    }

    if (attrs.subject !== undefined && typeof attrs.subject !== 'string') {
      addError('subject', 'If providing a subject, it must be provided as a string.');
    } else if (attrs.subject.length > max.subjectLength) {
      addError('subject', `The subject exceeds the max length of ${max.subjectLength}`);
    } else if (this.isGroupChatMessage && !attrs.subject) {
      addError('subject', 'A subject is required for a group chat message.');
    }

    if (attrs.message.length > max.messageLength) {
      addError('message', `The message exceeds the max length of ${max.messageLength}`);
    }

    if (Object.keys(errObj).length) return errObj;

    return undefined;
  }

  sync(method, model, options) {
    options.attrs = options.attrs || model.toJSON(options);

    if (method === 'create') {
      const timestamp = new Date().toISOString();
      options.attrs.timestamp = timestamp;
      this.set('timestamp', timestamp);
    }

    return super.sync(method, model, options);
  }
}
<commit_msg>null check on the regex matcher in the chat message model<commit_after>import $ from 'jquery';
import is from 'is_js';
import { getEmojiByName } from '../../data/emojis';
import sanitizeHtml from 'sanitize-html';
import twemoji from 'twemoji';
import app from '../../app';
import BaseModel from '../BaseModel';

/**
 * Will return a processed chat messages with changes appropriate for the UI (e.g. emojis will be
 * twemojified, ob urls will be turned into links, etc...).
 */
export function processMessage(message) {
  if (typeof message !== 'string') {
    throw new Error('Please provide a message as a string.');
  }

  let processedMessage = message;

  // jquery's html function converts &'s to &amps which messes with some of our
  // string replacements, particulary when the &amps are in an ob link. So, we'll
  // replace them with something else and then replace them back later.
  processedMessage = processedMessage.replace(/&/g, '__ob-full-amp__')
    .replace(/&/g, '__ob-compact-amp__');

  let $message = $(`<div>${processedMessage}</div>`);
  const anchors = [];

  // Ensure any OB links, handles (must be @ prefaced) or GUIDS are turned into anchor tags.

  // First we'll pull out any existing anchors and set them aside since we want to
  // leave those alone (i.e. avoid wrapping a guid / handle that's already in an anchor in
  // another one).
  $message.find('a')
    .each((index, el) => {
      anchors.push(el);
      $(el).replaceWith($('<div />').addClass('__ob-replaced-anchor__'));
    });

  const wordsToAnchorify = [];
  const findWords = node => {
    if (node.nodeType === 3) {
      // It's a text node. Loop through each word and if it's a guid or handle we keep track of it
      // so later we'll wrap it in an anchor element.
      const words = node.textContent.replace(/\r\n/g, ' ')
        .replace('\n', ' ')
        .match(/\S+\s*/g);

      if (!words) return;

      words.forEach(word => {
        const w = word.trim();
        if (wordsToAnchorify.includes(w)) return;

        if ((w.startsWith('@') && w.length > 1) ||
          (w.startsWith('ob://') && w.length > 5) ||
          (w.startsWith('http://') && w.length >= 11) ||
          (w.startsWith('https://') && w.length >= 12) ||
          (w.startsWith('www.') && w.length >= 8)) {
          wordsToAnchorify.push(w);
        }
      });
    } else {
      node.childNodes.forEach(child => findWords(child));
    }
  };

  findWords($message[0]);

  processedMessage = $message.html();

  wordsToAnchorify.forEach(word => {
    let href = !is.url(word) && !word.startsWith('ob://') ?
      `#ob://${word}` : word;

    if (is.url(word)) {
      const link = document.createElement('a');
      link.setAttribute('href', word);
      if (link.protocol === 'file:') {
        href = `http://${word}`;
      }
    }

    processedMessage = processedMessage
      .split(word)
      .join(`<a href="${href}" class="clrTEm">${word}</a>`);
  });

  // restore the anchors we pulled out earlier
  $message = $(`<div>${processedMessage}</div>`);
  $message.find('.__ob-replaced-anchor__')
    .each((index, el) => {
      $(el).replaceWith($(anchors[index]).addClass('clrTEm'));
    });

  processedMessage = $message.html()
    .replace(/__ob-full-amp__/g, '&')
    .replace(/__ob-compact-amp__/g, '&');

  // convert any unicode emoji characters to images via Twemoji
  processedMessage = twemoji.parse(processedMessage,
    icon => (`../imgs/emojis/72X72/${icon}.png`));

  return processedMessage;
}

export default class ChatMessage extends BaseModel {
  defaults() {
    return {
      subject: '',
      message: '',
      read: false,
      outgoing: true,
    };
  }

  get idAttribute() {
    return 'messageId';
  }

  get isGroupChatMessage() {
    return !!this.get('peerIds');
  }

  static get max() {
    return {
      subjectLength: 500,
      messageLength: 20000,
    };
  }

  url() {
    return app.getServerUrl(`ob/${this.isGroupChatMessage ? 'groupchat' : 'chat'}/`);
  }

  set(key, val, options = {}) {
    // Handle both `"key", value` and `{key: value}` -style arguments.
    let attrs;
    let opts = options;

    if (typeof key === 'object') {
      attrs = key;
      opts = val || {};
    } else {
      (attrs = {})[key] = val;
    }

    if (typeof attrs.message === 'string') {
      // Convert any emoji placeholder (e.g :smiling_face:) into
      // emoji unicode characters.
      const emojiPlaceholderRegEx = new RegExp(':.+?:', 'g');
      const matches = attrs.message.match(emojiPlaceholderRegEx, 'g');

      if (matches) {
        matches.forEach(match => {
          const emoji = getEmojiByName(match);

          if (emoji && emoji.char) {
            attrs.message = attrs.message.replace(match, emoji.char);
          }
        });
      }

      // sanitize the message
      attrs.message = sanitizeHtml(attrs.message);

      // Generate a processed message with changes to the message that are specific to our UI.
      attrs.processedMessage = processMessage(attrs.message);
    } else {
      // The processedMessage is automatically derived from the message and should not
      // be set directly.
      delete attrs.processedMessage;
    }

    return super.set(attrs, opts);
  }

  validate(attrs) {
    const errObj = {};
    const addError = (fieldName, error) => {
      errObj[fieldName] = errObj[fieldName] || [];
      errObj[fieldName].push(error);
    };

    const max = this.constructor.max;

    if (!this.isGroupChatMessage) {
      if (!attrs.peerId) {
        addError('peerId', 'The peerId is required');
      }
    } else if (!Array.isArray(attrs.peerIds) || !attrs.peerIds.length) {
      addError('peerIds', 'peerIds must be provided as an array.');
    }

    if (attrs.subject !== undefined && typeof attrs.subject !== 'string') {
      addError('subject', 'If providing a subject, it must be provided as a string.');
    } else if (attrs.subject.length > max.subjectLength) {
      addError('subject', `The subject exceeds the max length of ${max.subjectLength}`);
    } else if (this.isGroupChatMessage && !attrs.subject) {
      addError('subject', 'A subject is required for a group chat message.');
    }

    if (attrs.message.length > max.messageLength) {
      addError('message', `The message exceeds the max length of ${max.messageLength}`);
    }

    if (Object.keys(errObj).length) return errObj;

    return undefined;
  }

  sync(method, model, options) {
    options.attrs = options.attrs || model.toJSON(options);

    if (method === 'create') {
      const timestamp = new Date().toISOString();
      options.attrs.timestamp = timestamp;
      this.set('timestamp', timestamp);
    }

    return super.sync(method, model, options);
  }
}
<|endoftext|>


<commit_before>var ws;
function WebSocketTest(server) {
    var ws;
    if ("WebSocket" in window) {
        ws = new WebSocket("ws://" + server + "/ws/");
        ws.onopen = function() {
            ws.send('get_status');
        };
        ws.onmessage = function (evt) {
            var type = evt.data.split(' ', 1)[0];
            var received_msg = evt.data.substring(evt.data.indexOf(' ') + 1)

            var msg = jQuery.parseJSON(received_msg);

            switch(type.toUpperCase()){
                case 'STATE':
                    change_state(msg['state']);
                    break;
                case 'SCHEDULER':
                    update_info(msg['scheduler']);
                    break;
                case 'TARGET':
                    update_info(msg['target']);
                    break;
                case 'STATUS':
                    change_state(msg['state']);

                    var scheduler = msg['observatory']['scheduler'];

                    // Fix times
                    scheduler['local_evening_astro_time'] = trim_time(scheduler['local_evening_astro_time']);
                    scheduler['local_morning_astro_time'] = trim_time(scheduler['local_morning_astro_time']);

                    scheduler['local_moon_illumination'] = scheduler['local_moon_illumination'] * 100;

                    update_info(scheduler);

                    update_info(msg['observatory']['mount']);
                    refresh_images();
                    $('#system_panel .timer').timer('reset');
                    break;
                case 'ENVIRONMENT':
                    update_environment(msg['data']);
                    break;
                case 'WEATHER':
                    update_info(msg['data']);
                    update_weather(msg['data']);
                    break;
                case 'CAMERA':
                    update_cameras(msg);
                    break;
                case 'SAYBOT':
                case 'PANSHELL':
                case 'PAN001':
                    add_chat_item(type, msg.message, msg.timestamp);
                    break;
                default:
                    break;
            }

        };
        ws.onclose = function() {
            toggle_status('off');
        };
    } else {
        toggle_status('error');
    }

    return ws;
}

function trim_time(t){
    var time = t;
    if (typeof(t) == 'string'){
        time = t.split(':').slice(0,-1).join(':');
    }
    return time;
}

function add_chat_item(name, msg, time){

    item = '
';
    item = item + ' ';
    item = item + '  ' + time +' UTC';
    item = item + '
';
    item = item + '    ';
    item = item + name;
    item = item + '    ';
    item = item + msg;
    item = item + '
';
    item = item + '
';

    $('#bot_chat').prepend(item);
}

function toggle_connection_icon(icon){
    console.log('Should toggle status here');
    // $(icon).toggleClass('success').toggleClass('danger');
    // $(icon).toggleClass('fa-check-circle-o').toggleClass('fa-exclamation-triangle');
}

function update_environment(info){
    try {
        var camera_info = info['camera_box'];
        $('.camera_box_humidity_00').html(camera_info['humidity']);
        $('.camera_box_temp_00').html(camera_info['temp_00']);
    } catch(err) {
        console.log(err);
    }

    try {
        var computer_info = info['computer_box'];
        $('.computer_box_humidity_00').html(computer_info['humidity']);
        $('.computer_box_temp_00').html(computer_info['temp_00']);
        $('.computer_box_temp_01').html(computer_info['temp_01']);
        $('.computer_box_temp_02').html(computer_info['temp_02']);
        $('.computer_box_temp_03').html(computer_info['temp_03']);
    } catch(err) {
        console.log(err);
    }
}

function update_weather(is_safe){
    if(is_safe){
        $('.safe_condition').html('Safe');
        $('.title-bar').removeClass('danger');
        $('.callout').removeClass('unsafe_borders').addClass('safe_borders');
    } else {
        $('.safe_condition').html('Unsafe');
        $('.title-bar').addClass('danger');
        $('.callout').addClass('unsafe_borders').removeClass('safe_borders');
    }
    $('#weather_panel .timer').timer('reset');
}

function toggle_status(status){
    var icon = $('.current_state i');
    var text = $('.current_state span');

    icon.removeClass().addClass('fa');
    if (status == 'on'){
        icon.addClass('fa-circle').addClass('success');
        text.html('Online');
    } else if (status == 'off'){
        icon.addClass('fa-bolt').addClass('danger');
        text.html('Offline').addClass('danger');
    } else {
        icon.addClass('fa-exclamation-triangle', 'danger').addClass('danger');
        text.html('Error').addClass('danger');
    }
}

function change_state(state){
    var icon = $('.current_state i');
    var text = $('.current_state span');

    icon.removeClass().addClass('fa').addClass('success');
    text.html(state.toUpperCase());
    switch(state) {
        case 'analyzing':
            icon.addClass('fa-calculator');
            break;
        case 'tracking':
            icon.addClass('fa-binoculars');
            break;
        case 'observing':
            icon.addClass('fa-camera');
            break;
        case 'pointing':
            icon.addClass('fa-bullseye');
            break;
        case 'slewing':
            icon.addClass('fa-cog fa-spin');
            break;
        case 'scheduling':
            icon.addClass('fa-tasks');
            break;
        case 'ready':
            icon.addClass('fa-thumbs-o-up');
            break;
        case 'parking':
        case 'parked':
            icon.addClass('fa-car');
            break;
        case 'sleeping':
            icon.addClass('fa-check-circle');
            break;
        default:
            icon.addClass('fa-circle');
    }
    reload_img($('.state_img img'));
}

// Find all the elements with the class that matches a return value
// and update their html
function update_info(status){
    $.each(status, function(key, val){
        $('.' + key).each(function(idx, elem){
            $(elem).html(val);
        })
    });
}

function update_cameras(cameras){
    $.each(cameras, function(cam_name, props){
        $.each(props, function(prop, val){
            $('#' + cam_name + ' .' + prop).each(function(idx, elem){
                $(elem).html(val);
            });
            if (prop == 'exptime'){
                // Start the progress bar
                var pb = $('#' + cam_name + ' .progress-bar');
                pb.width('100%');

                var exptime = $('#' + cam_name + ' .exptime');
                exptime.html(val);

                var total_time = val;
                var count_time = val;

                var exp_count = $('#' + cam_name + ' .exp_count');
                // exp_count.timer('remove');
                exp_count.timer({
                    duration: '2s',
                    callback: function(){
                        count_time = count_time - 2;
                        var perc = (count_time/total_time) * 100;
                        console.log(perc);

                        if (perc < 0){
                            pb.width('0%');
                            exp_count.timer('remove');
                        } else {
                            pb.width(perc + '%');
                        }

                    },
                    repeat: true,
                });

                var pb_count = function(cb, count){
                    var width_perc = (count / val) * 100;
                    pb.width(width_perc + '%');
                    setTimeout(cb, 1000, cb, --count);
                };

                setTimeout(pb_count, 1000, pb_count, val);
            }
        });

    });

}

// Refresh all images with `img_refresh` container class
function refresh_images(){
    $.each($('.img_refresh img'), function(idx, img){
        reload_img(img);
    });
}

// Reload individual image
function reload_img(img){
    base = $(img).attr('src').split('?')[0];
    // console.log("Reloading image: " + $(img).attr('src'));

    // Hack for others
    if(base.startsWith('http')){
        new_src = $(img).attr('src');
    } else {
        new_src = base + '?' + Math.random()
    }

    $(img).attr('src', new_src);
}
<commit_msg>Better numbers<commit_after>var ws;
function WebSocketTest(server) {
    var ws;
    if ("WebSocket" in window) {
        ws = new WebSocket("ws://" + server + "/ws/");
        ws.onopen = function() {
            ws.send('get_status');
        };
        ws.onmessage = function (evt) {
            var type = evt.data.split(' ', 1)[0];
            var received_msg = evt.data.substring(evt.data.indexOf(' ') + 1)

            var msg = jQuery.parseJSON(received_msg);

            switch(type.toUpperCase()){
                case 'STATE':
                    change_state(msg['state']);
                    break;
                case 'SCHEDULER':
                    update_info(msg['scheduler']);
                    break;
                case 'TARGET':
                    update_info(msg['target']);
                    break;
                case 'STATUS':
                    change_state(msg['state']);

                    var scheduler = msg['observatory']['scheduler'];

                    // Fix times
                    scheduler['local_evening_astro_time'] = trim_time(scheduler['local_evening_astro_time']);
                    scheduler['local_morning_astro_time'] = trim_time(scheduler['local_morning_astro_time']);

                    scheduler['local_moon_illumination'] = parseFloat(scheduler['local_moon_illumination'] * 100).toFixed(2);

                    update_info(scheduler);

                    update_info(msg['observatory']['mount']);
                    refresh_images();
                    $('#system_panel .timer').timer('reset');
                    break;
                case 'ENVIRONMENT':
                    update_environment(msg['data']);
                    break;
                case 'WEATHER':
                    update_info(msg['data']);
                    update_weather(msg['data']);
                    break;
                case 'CAMERA':
                    update_cameras(msg);
                    break;
                case 'SAYBOT':
                case 'PANSHELL':
                case 'PAN001':
                    add_chat_item(type, msg.message, msg.timestamp);
                    break;
                default:
                    break;
            }

        };
        ws.onclose = function() {
            toggle_status('off');
        };
    } else {
        toggle_status('error');
    }

    return ws;
}

function trim_time(t){
    var time = t;
    if (typeof(t) == 'string'){
        time = t.split(':').slice(0,-1).join(':');
    }
    return time;
}

function add_chat_item(name, msg, time){

    item = '
';
    item = item + ' ';
    item = item + '  ' + time +' UTC';
    item = item + '
';
    item = item + '    ';
    item = item + name;
    item = item + '    ';
    item = item + msg;
    item = item + '
';
    item = item + '
';

    $('#bot_chat').prepend(item);
}

function toggle_connection_icon(icon){
    console.log('Should toggle status here');
    // $(icon).toggleClass('success').toggleClass('danger');
    // $(icon).toggleClass('fa-check-circle-o').toggleClass('fa-exclamation-triangle');
}

function update_environment(info){
    try {
        var camera_info = info['camera_box'];
        $('.camera_box_humidity_00').html(camera_info['humidity']);
        $('.camera_box_temp_00').html(camera_info['temp_00']);
    } catch(err) {
        console.log(err);
    }

    try {
        var computer_info = info['computer_box'];
        $('.computer_box_humidity_00').html(computer_info['humidity']);
        $('.computer_box_temp_00').html(computer_info['temp_00']);
        $('.computer_box_temp_01').html(computer_info['temp_01']);
        $('.computer_box_temp_02').html(computer_info['temp_02']);
        $('.computer_box_temp_03').html(computer_info['temp_03']);
    } catch(err) {
        console.log(err);
    }
}

function update_weather(is_safe){
    if(is_safe){
        $('.safe_condition').html('Safe');
        $('.title-bar').removeClass('danger');
        $('.callout').removeClass('unsafe_borders').addClass('safe_borders');
    } else {
        $('.safe_condition').html('Unsafe');
        $('.title-bar').addClass('danger');
        $('.callout').addClass('unsafe_borders').removeClass('safe_borders');
    }
    $('#weather_panel .timer').timer('reset');
}

function toggle_status(status){
    var icon = $('.current_state i');
    var text = $('.current_state span');

    icon.removeClass().addClass('fa');
    if (status == 'on'){
        icon.addClass('fa-circle').addClass('success');
        text.html('Online');
    } else if (status == 'off'){
        icon.addClass('fa-bolt').addClass('danger');
        text.html('Offline').addClass('danger');
    } else {
        icon.addClass('fa-exclamation-triangle', 'danger').addClass('danger');
        text.html('Error').addClass('danger');
    }
}

function change_state(state){
    var icon = $('.current_state i');
    var text = $('.current_state span');

    icon.removeClass().addClass('fa').addClass('success');
    text.html(state.toUpperCase());
    switch(state) {
        case 'analyzing':
            icon.addClass('fa-calculator');
            break;
        case 'tracking':
            icon.addClass('fa-binoculars');
            break;
        case 'observing':
            icon.addClass('fa-camera');
            break;
        case 'pointing':
            icon.addClass('fa-bullseye');
            break;
        case 'slewing':
            icon.addClass('fa-cog fa-spin');
            break;
        case 'scheduling':
            icon.addClass('fa-tasks');
            break;
        case 'ready':
            icon.addClass('fa-thumbs-o-up');
            break;
        case 'parking':
        case 'parked':
            icon.addClass('fa-car');
            break;
        case 'sleeping':
            icon.addClass('fa-check-circle');
            break;
        default:
            icon.addClass('fa-circle');
    }
    reload_img($('.state_img img'));
}

// Find all the elements with the class that matches a return value
// and update their html
function update_info(status){
    $.each(status, function(key, val){
        $('.' + key).each(function(idx, elem){
            $(elem).html(val);
        })
    });
}

function update_cameras(cameras){
    $.each(cameras, function(cam_name, props){
        $.each(props, function(prop, val){
            $('#' + cam_name + ' .' + prop).each(function(idx, elem){
                $(elem).html(val);
            });
            if (prop == 'exptime'){
                // Start the progress bar
                var pb = $('#' + cam_name + ' .progress-bar');
                pb.width('100%');

                var exptime = $('#' + cam_name + ' .exptime');
                exptime.html(val);

                var total_time = val;
                var count_time = val;

                var exp_count = $('#' + cam_name + ' .exp_count');
                // exp_count.timer('remove');
                exp_count.timer({
                    duration: '2s',
                    callback: function(){
                        count_time = count_time - 2;
                        var perc = (count_time/total_time) * 100;
                        console.log(perc);

                        if (perc < 0){
                            pb.width('0%');
                            exp_count.timer('remove');
                        } else {
                            pb.width(perc + '%');
                        }

                    },
                    repeat: true,
                });

                var pb_count = function(cb, count){
                    var width_perc = (count / val) * 100;
                    pb.width(width_perc + '%');
                    setTimeout(cb, 1000, cb, --count);
                };

                setTimeout(pb_count, 1000, pb_count, val);
            }
        });

    });

}

// Refresh all images with `img_refresh` container class
function refresh_images(){
    $.each($('.img_refresh img'), function(idx, img){
        reload_img(img);
    });
}

// Reload individual image
function reload_img(img){
    base = $(img).attr('src').split('?')[0];
    // console.log("Reloading image: " + $(img).attr('src'));

    // Hack for others
    if(base.startsWith('http')){
        new_src = $(img).attr('src');
    } else {
        new_src = base + '?' + Math.random()
    }

    $(img).attr('src', new_src);
}
<|endoftext|>


<commit_before>/*
  Module
  Synchronous dependency resolver.

  * What Is it?

    Module is a javascript dependency resolver. It helps you structure
    your app as modules.

    Basically, you define your app as a bunch of encapsulated
    modules.

    Each module is a function that lists its dependencies to other
    modules.

    You have one module called "main" that kicks everything off. That's
    pretty much all there is to it.

  * Why Does This Exist?

    RequireJS is a fine tool, but I had some issues with it. In
    production, you usually want to compress your assets into a single
    file and serve it as such. In development, you want to serve your
    assets separately. In dev mode with RequireJS, you perform
    asynchronous requests to the server to get modules, but this
    breaks parity with how you get assets in production (ie, in prod,
    all your files are in one big glob, so you don't need to hit the
    server).

    Usually, this makes no difference, but there are cases where it
    does. For example, if you're building an Ember app and define your
    routes in different modules - the app will fail if you try to
    navigate to a route before it's module file has been loaded. In
    production mode, however, it would work.

    In development and production, Module performs loading the same
    way; synchronously. It makes no difference if your files are
    served separately, concatenated, or minified.

  * Basic Usage

    To define a module:
      module.register(moduleName, function() {...})

    To include a module:
      module.register('foobar', function(moduleA, moduleB) {...})
    OR
      needs('moduleA', 'moduleB')

  * Where To Include Files

    Suggestions on where to include your asset files (ie, <head>,
    <body>) are only guidelines. Do what's best for your app.

    - Include this file in the <head> tag so it loads quickly.
    - Include your module definition files in the <body>.
    - You modules need to be defined before they can be loaded, so
      include your main module after your module definitions.

  ** Working With Third Party Libraries

     I prefer to simply leave third-party libraries as globals, but if
     you want to be very strictly modular, you can define adapters
     like so:

       module.register('$', function() {
         var jQuery = jQuery;
         window.$ = null;  // Remove global references to jQuery.
         window.jQuery = null;
         return jQuery;
       });

       module.register('Backbone', function() {
         var Backbone = Backbone;
         window.Backbone = null;
         return Backbone;
       });

    You might want to package all your adapters into a single
    module like this:

       module.register('adaptors', function() {

         module.register('$', function() {
           var jQuery = jQuery;
           window.$ = null;  // Remove global references to jQuery.
           window.jQuery = null;
           return jQuery;
         });

         module.register('Backbone', function() {
           var Backbone = Backbone;
           window.Backbone = null;
           return Backbone;
         });

         return module.needs(['$', 'Backbone'])

       });

    Then from your main module, you can do this:

      module.register('main', function() {
        runs('adaptors');  // Same as needs, but suppresses return value.
      });

  * Issues
    - Circular dependencies are an issue. Module fails if it
      detects if it detects one. For example, this is critically bad:

        module.register('foo', function(bar) {...});
        module.register('bar', function(foo) {...});

  * Guidelines For A Good Dependency Resolver
    - Doesn't get in the way of:
      - [X] Debugging
      - [X] Minification
      - [X] Gzip compression
      - [X] File concatentation
      - [X] Caching
    - [ ] File load order doesn't matter.
    - [X] Supports fast development/reloads.
    - [X] Production and development mode is the same.

  * Differences with RequireJS

    - The biggest difference is that this library doesn't do
      asynchronous loading in dev mode. Module is not a module loader,
      it is a dependency resolver whereas RequireJS is a module loader
      AND a dependency resolver. This actually makes it more
      comparable to Almond than RequireJS.

    - RequireJS executes code within a define block as soon as the
      file is loaded. Module waits until a module is needed before it
      executes its define block.

    - Doesn't come packaged with a directory traversal or file
      minification/concatenation tool akin r.js

    - Defined modules must be given names so they can be
      referenced. The downside to this is that names must be managed,
      but module referencing is more flexible.

    - With Module, you can define a module anywhere and as many as you
      want within a single file. You can also list and get
      dependencies anywhere you want. For example, this is perfectly valid code:

        // utils.js

        module.register('domUtils', function() {});
        module.register('strUtils', function(depA, depB) {

          // This has the same effect of listing "depC" in the parameters.
          var depC = needs('depC');

          // More includes.
          var moreDeps = needs(['app', 'math', 'trig']);

          for (var i=0; i < 4; i++) {

            // Registering modules dynamically.
            module.register('module' + i, function() {
              return i;
            }));

          }

        });

    - Dependencies can be listed in function parameters similar to
      AngularJS. Example:

        // RequireJS
        define(['app/app', 'utils/dom'], function(app, domUtils), {...});

        // Module
        module.register('main', function(app, domUtils) {...});

  * Similarities with RequireJS

    - Both require an entry point file. RequireJS requires a main.js
      file. Module simply requires you to register a module named
      "main".

  * TODO
    - Give it a trendy name. Eg, Tangler, Lasso, Curkit,
      standoff. "Module" is too generic and probably taken.
    - Write unit tests.
    - What about circular dependencies?
    - Detect circular dependencies and throw errors.
    - Allow global/default options.
    - In register, disallow any tag names that can't be used as in function params.
    - Allow namespace needs(). Eg,

        Allow separator option (default=/).
        needs:
         'editor: controller view', -> editor/controller, editor/view
         'gui: controller view'     -> editor/controller, editor/view

    - Document @options
    - Create option to log module load.

    - Confusing... Update this.modules{} to store Module objects
    - Change "register" -> "define"

    - Add a module.config function to set default options

    - Update merge function to accept multiple params.

    - Don't create a loader initially. Do this: var package = new Loader; // global
      so you can split things up into different packages.

*/

(function(context) {

  'use strict';

  function hasKey(obj, key) {
    return obj.hasOwnProperty(key);
  }

  // arguments -> array
  function toArr(args) {
    return Array.prototype.slice.call(args);
  }

  // Merges object @right into object @left and returns object @left.
  function merge(left, right) {
    for (var key in right) {
      if (hasKey(right, key))
        left[key] = right[key];
    }
    return left;
  }

  // Gets function parameters as a list of strings.
  // Source: http://stackoverflow.com/a/9924463/376590
  function getFnParams(fn) {
    var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
    var fnStr = fn.toString().replace(STRIP_COMMENTS, '');
    var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(/([^\s,]+)/g);
    if (result == null)
      result = [];
    return result;
  }

  function Loader() {

    this.modules = {
      /*
        def     : fn,
        cache   : fn,
        options : {}
      */
    };

    this.defaultModuleOptions = {
      loadNow: false,
      logOnLoad: false
    };

    this.nthModuleLoaded = 0;

  };

  // TODO: Make the loader use this format: {
  //   foo: {module: ..., cache: ..., options}
  // }

  var loader = new Loader();

  // Loader methods.
  merge(Loader.prototype, {

    exists: function(moduleName) {
      return hasKey(this.modules, moduleName);
    },

    isRegistered: function(moduleName) {
      return this.exists(moduleName) && hasKey(this.modules[moduleName], 'def');
    },

    inCache: function(moduleName) {
      return this.exists(moduleName) && hasKey(this.modules[moduleName], 'cache');
    },

    // Get a module. If it doesn't exist, throw an error.
    getDef: function(moduleName) {
      if (this.isRegistered(moduleName))
        return this.modules[moduleName].def;
      else
        throw 'ModuleError: Module [' + moduleName + '] not found as definition.';
    },

    define: function(moduleName, fn, options) {
      if (!this.exists(moduleName)) {
        this.modules[moduleName] = {
          options: merge(merge({}, loader.defaultModuleOptions), options)
        };
      }
      return this.modules[moduleName].def = fn;
    },

    // Get a cached module. If it doesn't exist, throw an error.
    queryCache: function(moduleName) {
      if (this.inCache(moduleName))
        return this.modules[moduleName].cache;
      else
        throw 'ModuleError: Module [' + moduleName + '] not found in cache.';
    },

    cache: function(moduleName, fn) {
      if (!this.exists(moduleName))
        throw "ModuleError: Module [" + moduleName + "] has not been registered."
      return this.modules[moduleName].cache = fn;
    },

    // Loads a module and its dependencies.
    load: function(moduleName) {

      if (!this.inCache(moduleName)) {

        var module = this.getDef(moduleName);
        var paramNames = getFnParams(module);
        var args = [];

        for (var i=0; i < paramNames.length; i++)
          args.push(this.load(paramNames[i]));

        this.nthModuleLoaded += 1;

        var moduleThis = {
          moduleName         : moduleName,
          moduleParams       : paramNames,
          moduleOptions      : this.modules[moduleName].options,
          moduleLoadPosition : this.nthModuleLoaded
        };

        if (this.modules[moduleName].options.logOnLoad)
          console.log('Module #' + this.nthModuleLoaded + ': Loading [' + moduleName + ']');

        this.cache(moduleName, module.apply(moduleThis, args));

      }

      return this.queryCache(moduleName);

    },

    /*
      Register a module. Similar to RequireJS's define function. Names
      are case-sensitive.
    */
    register: function(tag, fn, options) {

      /*

        options: {

          @loadNow: Load the module right now, without any other
          module calling it as a dependency. Be careful with this
          option as it allows your app to undermine the behavoir or
          "main" by having multiple entry points.

          @logOnLoad: Show a message when this module is loaded.

        }

      */

      if (typeof options === 'undefined')
        var options = {};

      // Problem: This sets the options property on the loader object, not the module.
      // this.options = merge(merge({}, this.defaultOptions), options);

      if (typeof tag !== 'string')
        throw "ModuleError: First parameter must be a unique tag string for the module.";
      else if (tag.length == 0)
        throw "ModuleError: Tag cannot be an empty string.";
      else if (this.isRegistered(tag))
        throw "ModuleError: Module [" + tag + "] already exists.";

      this.define(tag, fn);
      if (tag === 'main' || options.loadNow)
        this.load(tag);

    }

  });

  /*
    Calls module.load, but more flexible in terms of arguments.These
    all return the same result.

      needs('foo', 'bar');
      needs(['foo', 'bar']);
      needs('foo bar');
      needs('foo').concat(needs('bar'));
  */
  context.needs = function(moduleNames) {

    if (arguments.length > 1)
      return context.needs(toArr(arguments));

    if (typeof moduleNames === 'string') {
      var split = moduleNames.split(' ');
      if (split.length > 1)
        moduleNames = split;
      else
        return loader.load(moduleNames);
    }

    if (moduleNames instanceof Array) {
      var moduleRets = {};
      for (var i=0; i < moduleNames.length; i++) {
        var name = moduleNames[i];
        moduleRets[name] = loader.load(name);
      }
      return moduleRets;
    }

  };

  // Alias for needs(), but suppresses return value. You can always
  // use needs() instead, but calling this instead makes it clear that
  // you care only about the module's definition code, not whatever
  // (if anything) the module returns.
  context.runs = function() {
    needs.apply(null, arguments);
    return null;
  };

  context.module = loader;

})(window);
<commit_msg>Module now called Pillar. Pillar.Package defined.<commit_after>/*
  Pillar
  Synchronous dependency resolver.

  * What Is it?

    Module is a javascript dependency resolver. It helps you structure
    your app as modules.

    Basically, you define your app as a bunch of encapsulated
    modules.

    Each module is a function that lists its dependencies to other
    modules.

    You have one module called "main" that kicks everything off. That's
    pretty much all there is to it.

  * Why Does This Exist?

    RequireJS is a fine tool, but I had some issues with it. In
    production, you usually want to compress your assets into a single
    file and serve it as such. In development, you want to serve your
    assets separately. In dev mode with RequireJS, you perform
    asynchronous requests to the server to get modules, but this
    breaks parity with how you get assets in production (ie, in prod,
    all your files are in one big glob, so you don't need to hit the
    server).

    Usually, this makes no difference, but there are cases where it
    does. For example, if you're building an Ember app and define your
    routes in different modules - the app will fail if you try to
    navigate to a route before it's module file has been loaded. In
    production mode, however, it would work.

    In development and production, Module performs loading the same
    way; synchronously. It makes no difference if your files are
    served separately, concatenated, or minified.

  * Basic Usage

    To define a module:
      module.define(moduleName, function() {...})

    To include a module:
      module.define('foobar', function(moduleA, moduleB) {...})
    OR
      needs('moduleA', 'moduleB')

  * Where To Include Files

    Suggestions on where to include your asset files (ie, <head>,
    <body>) are only guidelines. Do what's best for your app.

    - Include this file in the <head> tag so it loads quickly.
    - Include your module definition files in the <body>.
    - You modules need to be defined before they can be loaded, so
      include your main module after your module definitions.

  ** Working With Third Party Libraries

     I prefer to simply leave third-party libraries as globals, but if
     you want to be very strictly modular, you can define adapters
     like so:

       module.define('$', function() {
         var jQuery = jQuery;
         window.$ = null;  // Remove global references to jQuery.
         window.jQuery = null;
         return jQuery;
       });

       module.define('Backbone', function() {
         var Backbone = Backbone;
         window.Backbone = null;
         return Backbone;
       });

    You might want to package all your adapters into a single
    module like this:

       module.define('adaptors', function() {

         module.define('$', function() {
           var jQuery = jQuery;
           window.$ = null;  // Remove global references to jQuery.
           window.jQuery = null;
           return jQuery;
         });

         module.define('Backbone', function() {
           var Backbone = Backbone;
           window.Backbone = null;
           return Backbone;
         });

         return module.needs(['$', 'Backbone'])

       });

    Then from your main module, you can do this:

      module.define('main', function() {
        runs('adaptors');  // Same as needs, but suppresses return value.
      });

  * Issues
    - Circular dependencies are an issue. Module fails if it
      detects if it detects one. For example, this is critically bad:

        module.define('foo', function(bar) {...});
        module.define('bar', function(foo) {...});

  * Guidelines For A Good Dependency Resolver
    - Doesn't get in the way of:
      - [X] Debugging
      - [X] Minification
      - [X] Gzip compression
      - [X] File concatentation
      - [X] Caching
    - [ ] File load order doesn't matter.
    - [X] Supports fast development/reloads.
    - [X] Production and development mode is the same.

  * Differences with RequireJS

    - The biggest difference is that this library doesn't do
      asynchronous loading in dev mode. Module is not a module loader,
      it is a dependency resolver whereas RequireJS is a module loader
      AND a dependency resolver. This actually makes it more
      comparable to Almond than RequireJS.

    - RequireJS executes code within a define block as soon as the
      file is loaded. Module waits until a module is needed before it
      executes its define block.

    - Doesn't come packaged with a directory traversal or file
      minification/concatenation tool akin r.js

    - Defined modules must be given names so they can be
      referenced. The downside to this is that names must be managed,
      but module referencing is more flexible.

    - With Module, you can define a module anywhere and as many as you
      want within a single file. You can also list and get
      dependencies anywhere you want. For example, this is perfectly valid code:

        // utils.js

        module.define('domUtils', function() {});
        module.define('strUtils', function(depA, depB) {

          // This has the same effect of listing "depC" in the parameters.
          var depC = needs('depC');

          // More includes.
          var moreDeps = needs(['app', 'math', 'trig']);

          for (var i=0; i < 4; i++) {

            // Defining modules dynamically.
            module.define('module' + i, function() {
              return i;
            }));

          }

        });

    - Dependencies can be listed in function parameters similar to
      AngularJS. Example:

        // RequireJS
        define(['app/app', 'utils/dom'], function(app, domUtils), {...});

        // Module
        module.define('main', function(app, domUtils) {...});

  * Similarities with RequireJS

    - Both require an entry point file. RequireJS requires a main.js
      file. Module simply requires you to define a module named
      "main".

  * TODO
    - Give it a trendy name. Eg, Tangler, Lasso, Curkit,
      standoff. "Module" is too generic and probably taken.
    - Write unit tests.
    - What about circular dependencies?
    - Detect circular dependencies and throw errors.
    - Allow global/default options.
    - In define, disallow any moduleNames that can't be used as in function params?
    - Disallow certain characters so that namespacing works.
    - Allow namespace needs(). Eg,

        Allow separator option (default=/).
        needs:
         'editor: controller view', -> editor/controller, editor/view
         'gui: controller view'     -> editor/controller, editor/view

    - Document @options
    - Create option to log module load.

    - Confusing... Update this.modules{} to store Module objects
    - Change "define" -> "define"

    - Add a module.config function to set default options

    - Update merge function to accept multiple params.

    - Don't create a loader initially. Do this: var package = new Loader; // global
      so you can split things up into different packages.

    - s/module/pillar

    - Add @logAfterLoad option

    - Revisit the isDefined function, this does the same thing as exists doesn't it?

*/

var pillar = (function() {

  'use strict';

  function hasKey(obj, key) {
    return obj.hasOwnProperty(key);
  }

  // arguments -> array
  function toArr(args) {
    return Array.prototype.slice.call(args);
  }

  // Merges object @right into object @left and returns object @left.
  function merge(left, right) {
    for (var key in right) {
      if (hasKey(right, key))
        left[key] = right[key];
    }
    return left;
  }

  // Gets function parameters as a list of strings.
  // Source: http://stackoverflow.com/a/9924463/376590
  function getFnParams(fn) {
    var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
    var fnStr = fn.toString().replace(STRIP_COMMENTS, '');
    var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(/([^\s,]+)/g);
    if (result == null)
      result = [];
    return result;
  }

  function Package() {

    this.modules = {
      /*
        def     : fn,
        cache   : fn,
        options : {}
      */
    };

    this.defaultModuleOptions = {
      loadNow: false,
      logOnLoad: false
    };

    this.nthModuleLoaded = 0;

  };

  // Package methods
  merge(Package.prototype, {

    exists: function(moduleName) {
      return hasKey(this.modules, moduleName);
    },

    isDefined: function(moduleName) {
      return this.exists(moduleName) && hasKey(this.modules[moduleName], 'def');
    },

    inCache: function(moduleName) {
      return this.exists(moduleName) && hasKey(this.modules[moduleName], 'cache');
    },

    // Get a module. If it doesn't exist, throw an error.
    getDef: function(moduleName) {
      if (this.isDefined(moduleName))
        return this.modules[moduleName].def;
      else
        throw 'ModuleError: Module [' + moduleName + '] not found as definition.';
    },

    addModule: function(moduleName, fn, options) {
      if (!this.exists(moduleName)) {
        this.modules[moduleName] = {
          options: merge(merge({}, this.defaultModuleOptions), options)
        };
      }
      return this.modules[moduleName].def = fn;
    },

    // Get a cached module. If it doesn't exist, throw an error.
    queryCache: function(moduleName) {
      if (this.inCache(moduleName))
        return this.modules[moduleName].cache;
      else
        throw 'ModuleError: Module [' + moduleName + '] not found in cache.';
    },

    cache: function(moduleName, fn) {
      if (!this.exists(moduleName))
        throw "ModuleError: Module [" + moduleName + "] has not been defined."
      return this.modules[moduleName].cache = fn;
    },

    // Loads a module and its dependencies.
    load: function(moduleName) {

      if (!this.inCache(moduleName)) {

        var module = this.getDef(moduleName);
        var paramNames = getFnParams(module);
        var args = [];

        for (var i=0; i < paramNames.length; i++)
          args.push(this.load(paramNames[i]));

        this.nthModuleLoaded += 1;

        if (this.modules[moduleName].options.logOnLoad)
          console.log('Module #' + this.nthModuleLoaded + ': Loading [' + moduleName + ']');

        var moduleThis = {
          moduleName         : moduleName,
          moduleParams       : paramNames,
          moduleOptions      : this.modules[moduleName].options,
          moduleLoadPosition : this.nthModuleLoaded
        };

        this.cache(moduleName, module.apply(moduleThis, args));

      }

      return this.queryCache(moduleName);

    },

    /*
      Define a module. Similar to RequireJS's define function. The
      module name is case-sensitive.
    */
    define: function(moduleName, fn, options) {

      /*

        options: {

          @loadNow: Load the module right now, without any other
          module calling it as a dependency. Be careful with this
          option as it allows your app to undermine the behavoir or
          "main" by having multiple entry points.

          @logOnLoad: Show a message when this module is loaded.

        }

      */

      if (typeof options === 'undefined')
        var options = {};

      // Problem: This sets the options property on the loader object, not the module.
      // this.options = merge(merge({}, this.defaultOptions), options);

      if (typeof moduleName !== 'string')
        throw "ModuleError: First parameter must be a unique string to identify the module.";
      else if (moduleName.length == 0)
        throw "ModuleError: Module name cannot be an empty string.";
      else if (this.isDefined(moduleName))
        throw "ModuleError: Module [" + moduleName + "] already exists.";

      this.addModule(moduleName, fn, options);
      if (moduleName === 'main' || options.loadNow)
        this.load(moduleName);

    }

  });

  function Module() {
  }

  merge(Module.prototype, {
  });

  /*
    Calls module.load, but more flexible in terms of arguments.These
    all return the same result.

      needs('foo', 'bar');
      needs(['foo', 'bar']);
      needs('foo bar');
      needs('foo').concat(needs('bar'));
  */
  window.needs = function(moduleNames) {

    if (arguments.length > 1)
      return window.needs(toArr(arguments));

    if (typeof moduleNames === 'string') {
      var split = moduleNames.split(' ');
      if (split.length > 1)
        moduleNames = split;
      else
        return loader.load(moduleNames);
    }

    if (moduleNames instanceof Array) {
      var moduleRets = {};
      for (var i=0; i < moduleNames.length; i++) {
        var name = moduleNames[i];
        moduleRets[name] = loader.load(name);
      }
      return moduleRets;
    }

  };

  // Alias for needs(), but suppresses return value. You can always
  // use needs() instead, but calling this instead makes it clear that
  // you care only about the module's definition code, not whatever
  // (if anything) the module returns.
  window.runs = function() {
    needs.apply(null, arguments);
    return null;
  };

  return {'Package': Package};

})();

// call it pillar
// pillar.package
// pillar.Package.Module<|endoftext|>


<commit_before>app.factory('socket', function ($rootScope) {
  var socket = io.connect('localhost'), {reconnect: true});
  return {
      joinRoom: function(roomName, playerName, isObserver) {
        socket.emit('joinRoom', roomName, playerName, isObserver);
      },
      leaveRoom: function() {
        socket.emit('leaveRoom');
      },
      updateRoom: function(callback) {
          socket.on('updateRoom', callback);
      },
      updateRoomList: function(callback) {
          socket.on('updateRoomList', callback);
      },
      getActiveRooms: function(roomList) {
          socket.emit('getActiveRooms', roomList);
      },
      setEstimate: function(value) {
        socket.emit('setEstimate', value);
      },
      toggleCards: function() {
        socket.emit('toggleCards');
      },
      resetHistory: function() {
        socket.emit('resetHistory');
      },
      setNextStory: function(nextStory) {
        socket.emit('nextStory', nextStory);
      },
      getSocketId: function() {
        return socket.id;
      }

  };
});<commit_msg>Fixing connection<commit_after>app.factory('socket', function ($rootScope) {
  var socket = io.connect(), {reconnect: true});
  return {
      joinRoom: function(roomName, playerName, isObserver) {
        socket.emit('joinRoom', roomName, playerName, isObserver);
      },
      leaveRoom: function() {
        socket.emit('leaveRoom');
      },
      updateRoom: function(callback) {
          socket.on('updateRoom', callback);
      },
      updateRoomList: function(callback) {
          socket.on('updateRoomList', callback);
      },
      getActiveRooms: function(roomList) {
          socket.emit('getActiveRooms', roomList);
      },
      setEstimate: function(value) {
        socket.emit('setEstimate', value);
      },
      toggleCards: function() {
        socket.emit('toggleCards');
      },
      resetHistory: function() {
        socket.emit('resetHistory');
      },
      setNextStory: function(nextStory) {
        socket.emit('nextStory', nextStory);
      },
      getSocketId: function() {
        return socket.id;
      }

  };
});<|endoftext|>


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

  var jCore = require('jcore');
  var helper = app.helper || require('../helper.js');

  var LockRelation = helper.inherits(function(props) {
    this.type = props.type;
    this.unit = props.unit;
    this.wire = props.wire;
  }, jCore.Relation);

  LockRelation.prototype.equal = function(other) {
    return (!!other && Object.keys(this).every(function(key) {
      return helper.equal(this[key], other[key]);
    }.bind(this)));
  };

  LockRelation.prototype.set = function() {
    this.unit.addRelation(this);
  };

  LockRelation.prototype.unset = function() {
    this.unit.removeRelation(this);
  };

  LockRelation.prototype.unitPosition = function() {
    return this.unit[this.type.positionMethodName]();
  };

  LockRelation.prototype.wirePosition = function(position) {
    var wire = this.wire;
    var positionType = this.type.positionType;
    wire[positionType + 'X'](position.x);
    wire[positionType + 'Y'](position.y);
  };

  LockRelation.prototype.update = function() {
    this.wirePosition(this.unitPosition());
  };

  LockRelation.TYPE_PLUG = {
    positionMethodName: 'portPlugPosition',
    positionType: 'source',
  };

  LockRelation.TYPE_SOCKET = {
    positionMethodName: 'portSocketPosition',
    positionType: 'target',
  };

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = LockRelation;
  } else {
    app.LockRelation = LockRelation;
  }
})(this.app || (this.app = {}));
<commit_msg>Modify type object of lock-relation<commit_after>(function(app) {
  'use strict';

  var jCore = require('jcore');
  var helper = app.helper || require('../helper.js');

  var LockRelation = helper.inherits(function(props) {
    this.type = props.type;
    this.unit = props.unit;
    this.wire = props.wire;
  }, jCore.Relation);

  LockRelation.prototype.equal = function(other) {
    return (!!other && Object.keys(this).every(function(key) {
      return helper.equal(this[key], other[key]);
    }.bind(this)));
  };

  LockRelation.prototype.set = function() {
    this.unit.addRelation(this);
  };

  LockRelation.prototype.unset = function() {
    this.unit.removeRelation(this);
  };

  LockRelation.prototype.unitPosition = function() {
    return this.unit[this.type.positionMethodName]();
  };

  LockRelation.prototype.wirePosition = function(position) {
    this.wire[this.type.positionNameX](position.x);
    this.wire[this.type.positionNameY](position.y);
  };

  LockRelation.prototype.update = function() {
    this.wirePosition(this.unitPosition());
  };

  LockRelation.TYPE_PLUG = {
    positionMethodName: 'portPlugPosition',
    positionNameX: 'sourceX',
    positionNameY: 'sourceY',
  };

  LockRelation.TYPE_SOCKET = {
    positionMethodName: 'portSocketPosition',
    positionNameX: 'targetX',
    positionNameY: 'targetY',
  };

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = LockRelation;
  } else {
    app.LockRelation = LockRelation;
  }
})(this.app || (this.app = {}));
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { FormattedMessage } from 'react-intl'
import { reduxForm, Field, propTypes } from 'redux-form/immutable'
import { TextField } from 'redux-form-material-ui'
import EmailIcon from 'material-ui/svg-icons/communication/email'
import RaisedButton from 'material-ui/RaisedButton'
import P from 'components/P'
import Div from 'components/Div'
import messages from './messages'
import { email } from './validate'

const styles = {
  checkbox: {
    left: 0
  },
  text: {
    width: '100%'
  },
  register: {
    position: 'absolute',
    right: 0,
    bottom: 0
  },
  signinButton: {
    width: '100%'
  },
  forgotPassword: {
    marginTop: 0,
    textAlign: 'right'
  }
}

// based on: https://github.com/erikras/redux-form-material-ui/blob/master/example/src/Form.js
/* eslint-disable import/no-mutable-exports */
let RecoverPasswordForm = class RecoverPasswordForm extends Component {
  componentDidMount() {
    this.firstField // the Field
      .getRenderedComponent() // on Field, returns ReduxFormMaterialUITextField
      .getRenderedComponent() // on ReduxFormMaterialUITextField, returns TextField
      .focus() // on TextField
  }

  componentWillMount() {
    if (!email(this.props.email)) {
      this.props.initialize({ username: this.props.email })
    }
  }

  email = (value) =>
    email(value) ? <FormattedMessage {...messages.invalidEmail} /> : undefined

  required = (value) =>
    value == null ? <FormattedMessage {...messages.required} /> : undefined

  render() {
    const { handleSubmit, submitting, pristine, email } = this.props
    this.firstField = email
    return (

{<FormattedMessage {...messages.recoverPasswordInfo} />}

        <form onSubmit={handleSubmit}>

            <Field
              name='username'
              component={TextField}
              ref={(input) => {
                this.firstField = input
              }}
              withRef
              style={styles.text}
              hintText={<FormattedMessage {...messages.email} />}
              floatingLabelText={<FormattedMessage {...messages.user} />}
              validate={[this.required, this.email]}
            />

            <RaisedButton
              style={styles.signinButton}
              label={<FormattedMessage {...messages.recoverPassword} />}
              primary={true}
              icon={<EmailIcon />}
              type='submit'
              disabled={pristine || submitting}
            />

        </form>

    )
  }
}

RecoverPasswordForm.propTypes = {
  ...propTypes
}
RecoverPasswordForm = reduxForm({
  form: 'signin',
  touchOnBlur: false,
  touchOnChange: true
  // enableReinitialize: true
  // fields
})(RecoverPasswordForm)

export default RecoverPasswordForm
<commit_msg>fix submit disable status<commit_after>import React, { Component } from 'react'
import { FormattedMessage } from 'react-intl'
import { reduxForm, Field, propTypes } from 'redux-form/immutable'
import { TextField } from 'redux-form-material-ui'
import EmailIcon from 'material-ui/svg-icons/communication/email'
import RaisedButton from 'material-ui/RaisedButton'
import P from 'components/P'
import Div from 'components/Div'
import messages from './messages'
import { email } from './validate'

const styles = {
  checkbox: {
    left: 0
  },
  text: {
    width: '100%'
  },
  register: {
    position: 'absolute',
    right: 0,
    bottom: 0
  },
  signinButton: {
    width: '100%'
  },
  forgotPassword: {
    marginTop: 0,
    textAlign: 'right'
  }
}

// based on: https://github.com/erikras/redux-form-material-ui/blob/master/example/src/Form.js
/* eslint-disable import/no-mutable-exports */
let RecoverPasswordForm = class RecoverPasswordForm extends Component {
  state = { errors: false }

  componentDidMount() {
    this.firstField // the Field
      .getRenderedComponent() // on Field, returns ReduxFormMaterialUITextField
      .getRenderedComponent() // on ReduxFormMaterialUITextField, returns TextField
      .focus() // on TextField
  }

  componentWillMount() {
    if (!email(this.props.email)) {
      this.props.initialize({ username: this.props.email })
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.invalid) {
      this.setState({ errors: true })
    } else {
      this.setState({ errors: false })
    }
  }

  email = (value) =>
    email(value) ? <FormattedMessage {...messages.invalidEmail} /> : ''

  required = (value) =>
    value == null ? <FormattedMessage {...messages.required} /> : undefined

  render() {
    const { handleSubmit, submitting, pristine, email } = this.props
    this.firstField = email
    return (

{<FormattedMessage {...messages.recoverPasswordInfo} />}

        <form onSubmit={handleSubmit}>

            <Field
              name='username'
              component={TextField}
              ref={(input) => {
                this.firstField = input
              }}
              withRef
              style={styles.text}
              hintText={<FormattedMessage {...messages.email} />}
              floatingLabelText={<FormattedMessage {...messages.user} />}
              validate={[this.required, this.email]}
            />

            <RaisedButton
              style={styles.signinButton}
              label={<FormattedMessage {...messages.recoverPassword} />}
              primary={true}
              icon={<EmailIcon />}
              type='submit'
              disabled={this.state.errors || submitting}
            />

        </form>

    )
  }
}

RecoverPasswordForm.propTypes = {
  ...propTypes
}
RecoverPasswordForm = reduxForm({
  form: 'recoverPassword',
  touchOnBlur: false,
  touchOnChange: true
  // enableReinitialize: true
  // fields
})(RecoverPasswordForm)

export default RecoverPasswordForm
<|endoftext|>


<commit_before>/*
 * @license
 * Copyright 2015 TAKAHASHI kazunari
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
"use strict";

/**
 * @fileoverview Externs for moment.js 2.3.0
 * @externs
 */

/**
 * @interface
 * @author takahashikzn
 */
function Moment() {};

/**
 * @typedef {{seconds:?number, minutes:?number, hours:?number, weeks:?number, months:?number, years:?number}}
 */
Moment.DateRecord;

/**
 * @nosideeffects
 * @type {(function():!Moment|function(!Date):!Moment|function(!number):!Moment|function(!Array.<!number>):!Moment|function(!string, !(string|Array.<!string>)=):!Moment|function(!Moment):!Moment|function(!Moment.DateRecord):!Moment)}
 */
function moment() {};

/**
 * @interface
 * @author takahashikzn
 */
Moment.Duration = function() {};

/**
 * @since 1.6.0
 * @param {!number=} a
 * @return {!Moment}
 */
Moment.prototype.unix = function(a) {};

/**
 * @since 1.5.0
 * @type {(function():!Moment|function(!number):!Moment|function(!Array.<!number>):!Moment|function(!string, !string=, !string=):!Moment|function(!string, !Array.<!string>):!Moment|function(!Moment):!Moment|function(!Date):!Moment)}
 */
Moment.prototype.utc = function() {};

/**
 * @since 2.3.0
 * @param {!string} a
 * @return {!Moment}
 */
Moment.prototype.parseZone = function(a) {};

/**
 * @nosideeffects
 * @since 1.7.0
 * @return {!boolean}
 */
Moment.prototype.isValid = function() {};

/**
 * @since 1.3.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.millisecond = function() {};

/**
 * @since 1.3.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.milliseconds = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.second = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.seconds = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.minute = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.minutes = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.hour = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.hours = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.date = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.dates = function() {};

/**
 * @since 1.3.0
 * @type {(function():!number|function(!(number|string)):!Moment)}
 */
Moment.prototype.day = function() {};

/**
 * @since 1.3.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.days = function() {};

/**
 * @since 2.1.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.weekday = function() {};

/**
 * @since 2.1.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.isoWeekday = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.dayOfYear = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.week = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.weeks = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.isoWeek = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.isoWeeks = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!(number|string)):!Moment)}
 */
Moment.prototype.month = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!(number|string)):!Moment)}
 */
Moment.prototype.months = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.year = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.years = function() {};

/**
 * @since 2.1.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.weekYear = function() {};

/**
 * @since 2.1.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.isoWeekYear = function() {};

/**
 * @since 2.2.1
 * @param {!string} unit
 * @return {!number}
 */
Moment.prototype.get = function(unit) {};

/**
 * @since 2.2.1
 * @param {!string} unit
 * @param {!number} value
 * @return {!Moment}
 */
Moment.prototype.set = function(unit, value) {};

/**
 * @since 1.0.0
 * @type {(function(!string, !number):!Moment|function(!number, !string):!Moment|function(!Moment.Duration):!Moment|function(!Moment.DateRecord):!Moment)}
 */
Moment.prototype.add = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @type {(function(!string, !number):!Moment|function(!number, !string):!Moment|function(!Moment.Duration):!Moment|function(!Moment.DateRecord):!Moment)}
 */
Moment.prototype.subtract = function() {};

/**
 * @nosideeffects
 * @since 1.7.0
 * @param {!string} a
 * @return {!Moment}
 */
Moment.prototype.startOf = function(a) {};

/**
 * @nosideeffects
 * @since 1.7.0
 * @param {!string} a
 * @return {!Moment}
 */
Moment.prototype.endOf = function(a) {};

/**
 * @nosideeffects
 * @since 2.1.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @return {!Moment}
 */
Moment.prototype.max = function(a) {};

/**
 * @nosideeffects
 * @since 2.1.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @return {!Moment}
 */
Moment.prototype.min = function(a) {};

/**
 * @nosideeffects
 * @since 1.5.0
 * @return {!Moment}
 */
Moment.prototype.local = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @param {!string=} a
 * @return {!Moment}
 */
Moment.prototype.format = function(a) {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @param {!boolean=} a
 * @return {!Moment}
 */
Moment.prototype.fromNow = function(a) {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!boolean=} b
 * @return {!Moment}
 */
Moment.prototype.from = function(a, b) {};

/**
 * @nosideeffects
 * @since 1.3.0
 * @return {!Moment}
 */
Moment.prototype.calendar = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!string=} b
 * @param {!boolean=} c
 * @return {!number}
 */
Moment.prototype.diff = function(a, b, c) {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @return {!number}
 */
Moment.prototype.valueOf = function() {};

/**
 * @since 1.2.0
 * @type {(function():!number|function(!(number|string)):!Moment)}
 */
Moment.prototype.zone = function() {};

/**
 * @nosideeffects
 * @since 1.5.0
 * @return {!number}
 */
Moment.prototype.daysInMonth = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @return {!Date}
 */
Moment.prototype.toDate = function() {};

/**
 * @nosideeffects
 * @since 2.0.0
 * @return {!Moment.DateRecord}
 */
Moment.prototype.toJSON = function() {};

/**
 * @nosideeffects
 * @since 2.1.0
 * @return {!string}
 */
Moment.prototype.toISOString = function() {};

/**
 * @nosideeffects
 * @since 2.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!string=} b
 * @return {!boolean}
 */
Moment.prototype.isBefore = function(a, b) {};

/**
 * @nosideeffects
 * @since 2.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!string=} b
 * @return {!boolean}
 */
Moment.prototype.isSame = function(a, b) {};

/**
 * @nosideeffects
 * @since 2.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!string=} b
 * @return {!boolean}
 */
Moment.prototype.isAfter = function(a, b) {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @return {!boolean}
 */
Moment.prototype.isLearYear = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @return {!boolean}
 */
Moment.prototype.isDST = function() {};

/**
 * @nosideeffects
 * @since 2.3.0
 * @return {!boolean}
 */
Moment.prototype.isDSTShifted = function() {};

/**
 * @nosideeffects
 * @since 1.5.0
 * @param {?} a
 * @return {!boolean}
 */
Moment.prototype.isMoment = function(a) {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @type {(function(!number, !string=):!Moment.Duration|function(!Moment.DateRecord):!Moment.Duration)}
 */
Moment.prototype.duration = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @param {!boolean=} a
 * @return {!string}
 */
Moment.Duration.prototype.humanize = function(a) {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.milliseconds = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asMilliseconds = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.seconds = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asSeconds = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.minutes = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asMinutes = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.hours = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asHours = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.days = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asDays = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.months = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asMonths = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.years = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asYears = function() {};

/**
 * @since 2.1.0
 * @type {(function(!number, !string):!Moment.Duration|function(!number):!Moment.Duration|function(!Moment.Duration):!Moment.Duration|function(Object):!Moment.Duration)}
 */
Moment.Duration.prototype.add = function() {};

/**
 * @since 2.1.0
 * @type {(function(!number, !string):!Moment.Duration|function(!number):!Moment.Duration|function(!Moment.Duration):!Moment.Duration|function(Object):!Moment.Duration)}
 */
Moment.Duration.prototype.subtract = function() {};

/**
 * @since 2.1.0
 * @param {!string} a
 * @return {!number}
 */
Moment.Duration.prototype.as = function(a) {};

/**
 * @since 2.1.0
 * @param {!string} unit
 * @return {!number}
 */
Moment.Duration.prototype.get = function(unit) {};

/* === Utilities === */

/**
 * @since 2.3.0
 * @param {!string} unit
 * @return {!string}
 */
Moment.normalizeUnits = function(unit) {};

/**
 * @since 2.3.0
 * @param {?} a
 * @return {!Moment}
 */
Moment.invalid = function(a) {};
<commit_msg>bugfix<commit_after>/*
 * @license
 * Copyright 2015 TAKAHASHI kazunari
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
"use strict";

/**
 * @fileoverview Externs for moment.js 2.3.0
 * @externs
 */

/**
 * @interface
 * @author takahashikzn
 */
function Moment() {};

/**
 * @typedef {{seconds:?number, minutes:?number, hours:?number, weeks:?number, months:?number, years:?number}}
 */
Moment.DateRecord;

/**
 * @nosideeffects
 * @type {(function():!Moment|function(!Date):!Moment|function(!number):!Moment|function(!Array.<!number>):!Moment|function(!string, !(string|Array.<!string>)=):!Moment|function(!Moment):!Moment|function(!Moment.DateRecord):!Moment)}
 */
function moment() {};

/**
 * @interface
 * @author takahashikzn
 */
Moment.Duration = function() {};

/**
 * @since 1.6.0
 * @param {!number=} a
 * @return {!Moment}
 */
Moment.prototype.unix = function(a) {};

/**
 * @since 1.5.0
 * @type {(function():!Moment|function(!number):!Moment|function(!Array.<!number>):!Moment|function(!string, !string=, !string=):!Moment|function(!string, !Array.<!string>):!Moment|function(!Moment):!Moment|function(!Date):!Moment)}
 */
Moment.prototype.utc = function() {};

/**
 * @since 2.3.0
 * @param {!string} a
 * @return {!Moment}
 */
Moment.prototype.parseZone = function(a) {};

/**
 * @nosideeffects
 * @since 1.7.0
 * @return {!boolean}
 */
Moment.prototype.isValid = function() {};

/**
 * @since 1.3.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.millisecond = function() {};

/**
 * @since 1.3.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.milliseconds = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.second = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.seconds = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.minute = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.minutes = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.hour = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.hours = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.date = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.dates = function() {};

/**
 * @since 1.3.0
 * @type {(function():!number|function(!(number|string)):!Moment)}
 */
Moment.prototype.day = function() {};

/**
 * @since 1.3.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.days = function() {};

/**
 * @since 2.1.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.weekday = function() {};

/**
 * @since 2.1.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.isoWeekday = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.dayOfYear = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.week = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.weeks = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.isoWeek = function() {};

/**
 * @since 2.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.isoWeeks = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!(number|string)):!Moment)}
 */
Moment.prototype.month = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!(number|string)):!Moment)}
 */
Moment.prototype.months = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.year = function() {};

/**
 * @since 1.0.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.years = function() {};

/**
 * @since 2.1.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.weekYear = function() {};

/**
 * @since 2.1.0
 * @type {(function():!number|function(!number):!Moment)}
 */
Moment.prototype.isoWeekYear = function() {};

/**
 * @since 2.2.1
 * @param {!string} unit
 * @return {!number}
 */
Moment.prototype.get = function(unit) {};

/**
 * @since 2.2.1
 * @param {!string} unit
 * @param {!number} value
 * @return {!Moment}
 */
Moment.prototype.set = function(unit, value) {};

/**
 * @since 1.0.0
 * @type {(function(!string, !number):!Moment|function(!number, !string):!Moment|function(!Moment.Duration):!Moment|function(!Moment.DateRecord):!Moment)}
 */
Moment.prototype.add = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @type {(function(!string, !number):!Moment|function(!number, !string):!Moment|function(!Moment.Duration):!Moment|function(!Moment.DateRecord):!Moment)}
 */
Moment.prototype.subtract = function() {};

/**
 * @nosideeffects
 * @since 1.7.0
 * @param {!string} a
 * @return {!Moment}
 */
Moment.prototype.startOf = function(a) {};

/**
 * @nosideeffects
 * @since 1.7.0
 * @param {!string} a
 * @return {!Moment}
 */
Moment.prototype.endOf = function(a) {};

/**
 * @nosideeffects
 * @since 2.1.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @return {!Moment}
 */
Moment.prototype.max = function(a) {};

/**
 * @nosideeffects
 * @since 2.1.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @return {!Moment}
 */
Moment.prototype.min = function(a) {};

/**
 * @since 1.5.0
 * @return {!Moment}
 */
Moment.prototype.local = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @param {!string=} a
 * @return {!string}
 */
Moment.prototype.format = function(a) {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @param {!boolean=} a
 * @return {!string}
 */
Moment.prototype.fromNow = function(a) {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!boolean=} b
 * @return {!string}
 */
Moment.prototype.from = function(a, b) {};

/**
 * @nosideeffects
 * @since 1.3.0
 * @return {!string}
 */
Moment.prototype.calendar = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!string=} b
 * @param {!boolean=} c
 * @return {!number}
 */
Moment.prototype.diff = function(a, b, c) {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @return {!number}
 */
Moment.prototype.valueOf = function() {};

/**
 * @since 1.2.0
 * @type {(function():!number|function(!(number|string)):!Moment)}
 */
Moment.prototype.zone = function() {};

/**
 * @nosideeffects
 * @since 1.5.0
 * @return {!number}
 */
Moment.prototype.daysInMonth = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @return {!Date}
 */
Moment.prototype.toDate = function() {};

/**
 * @nosideeffects
 * @since 2.0.0
 * @return {!Moment.DateRecord}
 */
Moment.prototype.toJSON = function() {};

/**
 * @nosideeffects
 * @since 2.1.0
 * @return {!string}
 */
Moment.prototype.toISOString = function() {};

/**
 * @nosideeffects
 * @since 2.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!string=} b
 * @return {!boolean}
 */
Moment.prototype.isBefore = function(a, b) {};

/**
 * @nosideeffects
 * @since 2.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!string=} b
 * @return {!boolean}
 */
Moment.prototype.isSame = function(a, b) {};

/**
 * @nosideeffects
 * @since 2.0.0
 * @param {!(Moment|string|number|Date|Array.<!number>)} a
 * @param {!string=} b
 * @return {!boolean}
 */
Moment.prototype.isAfter = function(a, b) {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @return {!boolean}
 */
Moment.prototype.isLearYear = function() {};

/**
 * @nosideeffects
 * @since 1.0.0
 * @return {!boolean}
 */
Moment.prototype.isDST = function() {};

/**
 * @nosideeffects
 * @since 2.3.0
 * @return {!boolean}
 */
Moment.prototype.isDSTShifted = function() {};

/**
 * @nosideeffects
 * @since 1.5.0
 * @param {?} a
 * @return {!boolean}
 */
Moment.prototype.isMoment = function(a) {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @type {(function(!number, !string=):!Moment.Duration|function(!Moment.DateRecord):!Moment.Duration)}
 */
Moment.prototype.duration = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @param {!boolean=} a
 * @return {!string}
 */
Moment.Duration.prototype.humanize = function(a) {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.milliseconds = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asMilliseconds = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.seconds = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asSeconds = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.minutes = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asMinutes = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.hours = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asHours = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.days = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asDays = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.months = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asMonths = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.years = function() {};

/**
 * @nosideeffects
 * @since 1.6.0
 * @return {!number}
 */
Moment.Duration.prototype.asYears = function() {};

/**
 * @since 2.1.0
 * @type {(function(!number, !string):!Moment.Duration|function(!number):!Moment.Duration|function(!Moment.Duration):!Moment.Duration|function(Object):!Moment.Duration)}
 */
Moment.Duration.prototype.add = function() {};

/**
 * @since 2.1.0
 * @type {(function(!number, !string):!Moment.Duration|function(!number):!Moment.Duration|function(!Moment.Duration):!Moment.Duration|function(Object):!Moment.Duration)}
 */
Moment.Duration.prototype.subtract = function() {};

/**
 * @since 2.1.0
 * @param {!string} a
 * @return {!number}
 */
Moment.Duration.prototype.as = function(a) {};

/**
 * @since 2.1.0
 * @param {!string} unit
 * @return {!number}
 */
Moment.Duration.prototype.get = function(unit) {};

/* === Utilities === */

/**
 * @since 2.3.0
 * @param {!string} unit
 * @return {!string}
 */
Moment.normalizeUnits = function(unit) {};

/**
 * @since 2.3.0
 * @param {?} a
 * @return {!Moment}
 */
Moment.invalid = function(a) {};
<|endoftext|>