<commit_before>(function() {
	var formatMessage;

	$(function() {
		var socket;
		var $textarea = $("form.chat textarea");
		var $output = $("#output");
		socket = connect();
		socket.onopen = function(event) {
			$output.append("

").addClass("output_login").text("Connection with chat server established.");
		}
		socket.onmessage = function(event) {
			var $output, output;
			if (event.data.length) {
				handleMessage(event.data);
			}
		};
		socket.onclose = function(event) {
			$textarea.prop("disabled", true);
			$output.append("

").addClass("output_logout").text("Lost connection with server, retrying connection...");
			window.setTimeout(function(){
				connect();
			}, 5000);
		}
		$("body").on("submit", "form.chat", function(event) {
			var $textarea;
			event.preventDefault();
			$textarea = $(this).find("textarea");
			socket.send(formatMessage($textarea.val()));
			return $textarea.val(null);
		});
		$textarea.focus;
		return $textarea.on("keyup", function(event) {
			if (event.keyCode === 13 && !event.shiftKey && $textarea.val().length != 0) {
				return $("form.chat").submit();
			}
		});
	});
	connect = function() {
		return new WebSocket("ws://" + window.location.host + "/chat");
	}
	commands = [];
	commands["login"] = function(argument,$output) {
		if(argument){
			console.dir(argument);
			var divider = argument.indexOf(":");
			var newuser = argument.slice(0,divider);
			argument = argument.slice(divider+1,argument.length);
			replaceUserList(argument);
			var $elem = $("

").addClass("output_login").html("- " + newuser +" just logged in");
			$output.append($elem);

		}
	}

	commands["logout"] = function(argument,$output) {
		if(argument){
			console.log(argument);
			var divider = argument.indexOf(":");
			var olduser = argument.slice(0,divider);
			argument = argument.slice(divider+1,argument.length);
			replaceUserList(argument);
			var $elem = $("

").addClass("output_logout").html("- Bye bye " + olduser +"!");
			$output.append($elem);
		}
	}

	replaceUserList = function(argument) {
		var $container = $("#userlist").clone().empty();
		var me = $container.data("me");
		var members = $.parseJSON(argument);
		var $mold = $("

");
		var $elem;
		for(var i=0; i < members.length; i++) {
			$elem = $mold.clone().text(members[i]);
			if(members[i] == me) $elem.addClass("user_me");
			$container.append($elem);
		}
		$("#userlist").replaceWith($container);
	}
	formatMessage = function(message) {
		var me;
		me = $("#userlist").data("me");
		return me + ": " + message;
	};

	handleMessage = function(message) {
		if(message && message.length > 0) {
			var $output = $("#output");
			console.log("message: ", message);
			var matches = message.match(/(\[LH:)(\w+)(\])/);
			if(matches != undefined && matches != null && matches.length > 0 && matches[1] == "[LH:") {
				var command = matches[2];
				var argument = message.slice(command.length+5,message.length);
				commands[command](argument,$output);
			} else {
				var me = $("#userlist").data("me");
				message = message.replace(me, ""+me+"");
				var $elem = $("

").addClass("output_message").html(message);
				$output.append($elem);

			}
			var output = $output[0];
			return output.scrollTop = output.scrollHeight;

		}
	}

}).call(this);
<commit_msg>Refactor javascript to be contained in the window.loungeChat object and fixed the reconnection issue.<commit_after>(function() {
	window.loungeChat = {};
	lc = window.loungeChat;
	lc.elem = {};
	lc.connectionTimer = "test";
	lc.registerHandlers = function(){
		lc = window.loungeChat;
		socket = lc.socket;
		socket.onopen = function(event) {
			lc.elem.$textarea.prop("disabled", false);
			var $elem = $("

").addClass("output_login").text("Connection with chat server established.");
			lc.elem.$output.append($elem);
			clearTimeout(lc.connectionTimer);
		};
		socket.onmessage = function(event) {
			if (event.data.length) {
				lc.handleMessage(event.data);
			}
		};
		socket.onclose = function(event) {
			lc.elem.$textarea.prop("disabled", true);
			var $elem = $("

").addClass("output_logout").text("Lost connection with server, retrying connection...");
			lc.elem.$output.append($elem);
			lc.connectionTimer = window.setTimeout(lc.connect, 5000);
		};
	};
	lc.connect = function() {
		lc = window.loungeChat;
		console.info("Connecting to websocket", lc.connectionTimer);
		lc.socket = new WebSocket("ws://" + window.location.host + "/chat");
		lc.registerHandlers();
		// lc.connectionTimer = window.setTimeout(lc.connect, 5000);
	};
	lc.commands = [];
	lc.commands["login"] = function(argument) {
		if(argument) {
			console.dir(argument);
			var divider = argument.indexOf(":");
			var newuser = argument.slice(0,divider);
			argument = argument.slice(divider+1,argument.length);
			lc.replaceUserList(argument);
			var $elem = $("

").addClass("output_login").html("- " + newuser +" just logged in");
			window.loungeChat.elem.$output.append($elem);

		}
	};

	lc.commands["logout"] = function(argument) {
		if(argument){
			console.log(argument);
			var divider = argument.indexOf(":");
			var olduser = argument.slice(0,divider);
			argument = argument.slice(divider+1,argument.length);
			replaceUserList(argument);
			var $elem = $("

").addClass("output_logout").html("- Bye bye " + olduser +"!");
			window.loungeChat.elem.$output.append($elem);
		}
	};

	lc.replaceUserList = function(argument) {
		/* TODO: Refactor me later, extract members into window.loungeChat */
		var $container = $("#userlist").clone().empty();
		var me = $container.data("me");
		var members = $.parseJSON(argument);
		var $mold = $("

");
		var $elem;
		for(var i=0; i < members.length; i++) {
			$elem = $mold.clone().text(members[i]);
			if(members[i] == me) $elem.addClass("user_me");
			$container.append($elem);
		}
		$("#userlist").replaceWith($container);
	};
	lc.formatMessage = function(message) {
		var me;
		me = $("#userlist").data("me");
		return me + ": " + message;
	};

	lc.handleMessage = function(message) {
		if(message !== undefined && message.length > 0) {
			console.log("message: ", message);
			var matches = message.match(/(\[LH:)(\w+)(\])/);
			if(matches !== undefined && matches !== null && matches.length > 0 && matches[1] == "[LH:") {
				var command = matches[2];
				var argument = message.slice(command.length+5,message.length);
				lc.commands[command](argument,window.loungeChat.elem.$output);
			} else {
				var me = $("#userlist").data("me");
				message = message.replace(me, ""+me+"");
				var $elem = $("

").addClass("output_message").html(message);
				window.loungeChat.elem.$output.append($elem);

			}
			var output = window.loungeChat.elem.$output[0];
			output.scrollTop = output.scrollHeight;

		}
	};

	//INITIALIZER, let me come last please.
	$(function() {
		lc.elem.$textarea = $("form.chat textarea");
		lc.elem.$output = $("#output");
		lc.connect();
		lc.registerHandlers();
		$("body").on("submit", "form.chat", function(event) {
			event.preventDefault();
			lc.elem.$textarea = $(this).find("textarea");
			lc.socket.send(lc.formatMessage(lc.elem.$textarea.val()));
			return lc.elem.$textarea.val(null);
		});
		lc.elem.$textarea.focus();
		return lc.elem.$textarea.on("keyup", function(event) {
			if (event.keyCode === 13 && !event.shiftKey && lc.elem.$textarea.val().length !== 0) {
				return $("form.chat").submit();
			}
		});
	});

}).call(this);
<|endoftext|>


<commit_before>
jQuery(document).ready(function($){
  var search = $("#search");
  var submissions = $("#submissions tbody tr");
  search.keyup(function(event) {
    var filter = search.val();
    submissions.each(function(index, elem) {
      var $elem = $(elem);
      var studentNumber = $elem.data("student");
      if (!studentNumber) return;
      $elem.toggle(studentNumber.indexOf(filter) !== -1);
    });
  })
});
<commit_msg>Turbolinks fix<commit_after>$(document).on('ready page:load', function(){
  var search = $("#search");
  search.focus();
  var submissions = $("#submissions tbody tr");
  search.keyup(function(event) {
    var filter = search.val();
    submissions.each(function(index, elem) {
      var $elem = $(elem);
      var studentNumber = $elem.data("student");
      if (!studentNumber) return;
      $elem.toggle(studentNumber.indexOf(filter) !== -1);
    });
  })
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import styles from './TasksWall.scss';
import classNames from 'classnames/bind';
import {
  orderChange,
  moveFromTo
} from './actions';
import { findTask, findGroup } from '../../js/findUp';
import { getOffsetLeft, getOffsetTop } from '../../js/getOffset';
import resetInlineStyles from '../../js/resetInlineStyles';
import { Observable } from 'rxjs/Observable';

import TaskGroup from '../TaskGroup/TaskGroup';

const css = classNames.bind(styles);
const DRAG_ACTIVE = 'drag-active';

class TasksWall extends Component {

  constructor (props) {
    super(props);
  }

  componentDidMount () {
    const mouseDown = Observable.fromEvent(this._wall, 'mousedown');
    const mouseMove = Observable.fromEvent(this._wall, 'mousemove');
    const mouseUp = Observable.fromEvent(this._wall, 'mouseup');

    const mouseDrag = mouseDown
      .flatMap((e) => {
        const task = findTask(e.target);

        return Observable.of(task)
          .filter((task) => task && !task.classList.contains('js-editMode'))
          .map((task) => {
            const content = task.querySelector('.js-item-content');
            let data = {
              elem: content,
              groupFrom: findGroup(task),
              id: task.getAttribute('data-id'),
              title: task.querySelector('.js-task-title').innerHTML,
              description: task.querySelector('.js-task-description').innerHTML
            };
            let left = getOffsetLeft(content) + content.offsetWidth / 2;
            return { task, data, content, left };
          });
      })
      .flatMap((drag) => {
        return mouseMove
          .map((e) => ({ drag, e }))
          .takeUntil(mouseUp);
      });

      const mouseBufferDrag = mouseDrag
        .buffer(mouseUp)
        .filter((arr) => arr.length)
        .map((arr) => arr[arr.length - 1]);

      const mouseDragUp = Observable.zip(
        mouseBufferDrag,
        mouseUp,
        (obj, e) => ({ obj, e })
      )

    mouseDrag.subscribe(({ drag, e }) => {
      const { task, data, content, left } = drag;
      let top = getOffsetTop(content) - 10,
        x = e.x - left,
        y = e.y - top + document.scrollingElement.scrollTop;

      if (!document.body.classList.contains(DRAG_ACTIVE)) {
        document.body.classList.add(DRAG_ACTIVE);
        content.style.position = 'relative';
        task.firstChild.style.display = 'none';
        task.style.background = 'rgba(0, 0, 0, 0.1)';
        document.body.style.cursor = 'move';
      }

      content.style.transform = `translate(${x}px, ${y}px)`;
    });

    mouseDragUp.subscribe(({ obj, e }) => {
      const { elem, groupFrom, id, title, description } = obj.drag.data;
      const groupTo = findGroup(e.target);
      const task = findTask(e.target);
      let index = -1;
      if (task) {
        index = task.getAttribute('data-index');
        resetInlineStyles(task);
      }
      resetInlineStyles(elem, document.body, elem.parentNode.firstChild);
      document.body.classList.remove(DRAG_ACTIVE);

      if (groupFrom !== groupTo) {
        this.props.moveFromTo(id, title, description, groupFrom, groupTo, Number(index));
      } else {
        this.props.orderChange(id, title, description, groupFrom, Number(index));
      }
    });
  }

  render () {
    const { tasks } = this.props;
    return (

 this._wall = elem }>
        {
          Object.keys(tasks).map((key, i) => {
            return (
              <TaskGroup key={ `task-wall-${key}` } array={ tasks[key].data } groupKey={ key } name={ tasks[key].name } addbtn={ !i }/>
            );
          })
        }

    );
  }
}

const mapStateToProps = (state, ownProps) => {
  return {
    tasks: Object.assign({}, state.tasks)
  };
};

const mapDispatchToProps = (dispatch, ownProps) => bindActionCreators({
  orderChange,
  moveFromTo
}, dispatch);

export { TasksWall };
export default connect(mapStateToProps, mapDispatchToProps)(TasksWall);
<commit_msg>fix mouseUp zip<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import styles from './TasksWall.scss';
import classNames from 'classnames/bind';
import {
  orderChange,
  moveFromTo
} from './actions';
import { findTask, findGroup } from '../../js/findUp';
import { getOffsetLeft, getOffsetTop } from '../../js/getOffset';
import resetInlineStyles from '../../js/resetInlineStyles';
import { Observable } from 'rxjs/Observable';

import TaskGroup from '../TaskGroup/TaskGroup';

const css = classNames.bind(styles);
const DRAG_ACTIVE = 'drag-active';

class TasksWall extends Component {

  constructor (props) {
    super(props);
  }

  componentDidMount () {
    const mouseDown = Observable.fromEvent(this._wall, 'mousedown');
    const mouseMove = Observable.fromEvent(this._wall, 'mousemove');
    const mouseUp = Observable.fromEvent(this._wall, 'mouseup');

    const mouseDrag = mouseDown
      .flatMap((e) => {
        const task = findTask(e.target);

        return Observable.of(task)
          .filter((task) => task && !task.classList.contains('js-editMode'))
          .map((task) => {
            const content = task.querySelector('.js-item-content');
            let data = {
              elem: content,
              groupFrom: findGroup(task),
              id: task.getAttribute('data-id'),
              title: task.querySelector('.js-task-title').innerHTML,
              description: task.querySelector('.js-task-description').innerHTML
            };
            let left = getOffsetLeft(content) + content.offsetWidth / 2;
            return { task, data, content, left };
          });
      })
      .flatMap((drag) => {
        return mouseMove
          .map((e) => ({ drag, e }))
          .takeUntil(mouseUp);
      });

      const mouseBufferDrag = mouseDrag
        .buffer(mouseUp)
        .filter((arr) => arr.length)
        .map((arr) => arr[arr.length - 1]);

      const mouseDragUp = Observable.zip(
        mouseBufferDrag,
        mouseUp.filter((e) => e.target.classList.contains('g-fake-ondrag')),
        (obj, e) => ({ obj, e })
      );

    mouseDrag.subscribe(({ drag, e }) => {
      const { task, data, content, left } = drag;
      let top = getOffsetTop(content) - 10,
        x = e.x - left,
        y = e.y - top + document.scrollingElement.scrollTop;

      if (!document.body.classList.contains(DRAG_ACTIVE)) {
        document.body.classList.add(DRAG_ACTIVE);
        content.style.position = 'relative';
        task.firstChild.style.display = 'none';
        task.style.background = 'rgba(0, 0, 0, 0.1)';
        document.body.style.cursor = 'move';
      }

      content.style.transform = `translate(${x}px, ${y}px)`;
    });

    mouseDragUp.subscribe(({ obj, e }) => {
      const { elem, groupFrom, id, title, description } = obj.drag.data;
      const groupTo = findGroup(e.target);
      const task = findTask(e.target);
      let index = -1;
      if (task) {
        index = task.getAttribute('data-index');
        resetInlineStyles(task);
      }
      resetInlineStyles(elem, document.body, elem.parentNode.firstChild);
      document.body.classList.remove(DRAG_ACTIVE);

      if (groupFrom !== groupTo) {
        this.props.moveFromTo(id, title, description, groupFrom, groupTo, Number(index));
      } else {
        this.props.orderChange(id, title, description, groupFrom, Number(index));
      }
    });
  }

  render () {
    const { tasks } = this.props;
    return (

 this._wall = elem }>
        {
          Object.keys(tasks).map((key, i) => {
            return (
              <TaskGroup key={ `task-wall-${key}` } array={ tasks[key].data } groupKey={ key } name={ tasks[key].name } addbtn={ !i }/>
            );
          })
        }

    );
  }
}

const mapStateToProps = (state, ownProps) => {
  return {
    tasks: Object.assign({}, state.tasks)
  };
};

const mapDispatchToProps = (dispatch, ownProps) => bindActionCreators({
  orderChange,
  moveFromTo
}, dispatch);

export { TasksWall };
export default connect(mapStateToProps, mapDispatchToProps)(TasksWall);
<|endoftext|>


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

    angular
        .module('hdpuzzles')
        .service('audio', audioService);

    audioService.$inject = ['$window', 'soundEffects', 'settings'];

    function audioService ($window, soundEffects, settings) {
        var audio;

        return {
            "preload": preload,
            "playSoundEffect": playSoundEffect
        };

        function preload () {
            audio = new $window.Audio();
            audio.src = 'audio/swap_default.mp3';
            audio.play();
        }

        function playSoundEffect () {
            if (!settings.get('ENABLE_SOUND_EFFECTS')) {
                return;
            }

            //var audio = new $window.Audio();
            //alert(audio.muted);
            //audio.src = soundEffects[name];
            audio.play();
        }
    }
})();<commit_msg>ios9 audio workaround attempt #notcounting<commit_after>(function () {
    'use strict';

    angular
        .module('hdpuzzles')
        .service('audio', audioService);

    audioService.$inject = ['$window', 'soundEffects', 'settings'];

    function audioService ($window, soundEffects, settings) {
        var audio = {};

        return {
            "preload": preload,
            "playSoundEffect": playSoundEffect
        };

        function preload () {

            angular.forEach(soundEffects, function (name) {
                audio[name] = new $window.Audio();
                audio.src = 'audio/swap_default.mp3';
                audio.play();
            });
        }

        function playSoundEffect (name) {
            if (!settings.get('ENABLE_SOUND_EFFECTS')) {
                return;
            }

            audio[name].play();
        }
    }
})();<|endoftext|>


<commit_before>import Component from '@ember/component';
import { reads } from '@ember/object/computed';
import { computed } from '@ember/object';
import { task } from 'ember-concurrency';
import { inject as service } from '@ember/service';

export default Component.extend({
  flashes: service(),
  accounts: service(),

  account: null,
  subscription: null,
  autoRefillEnabled: reads('subscription.autoRefillEnabled'),
  autoRefillThreshold: reads('subscription.autoRefillThreshold'),
  autoRefillAmount: reads('subscription.autoRefillAmount'),
  autoRefillThresholds: reads('subscription.autoRefillThresholds'),
  autoRefillAmounts: reads('subscription.autoRefillAmounts'),

  creditsTotal: reads('subscription.addonUsage.private.totalCredits'),

  selectedThreshold: computed('autoRefillThreshold', function () {
    return this.autoRefillThreshold;
  }),

  selectedAmount: computed('autoRefillAmount', function () {
    return this.autoRefillAmount;
  }),

  autoRefillCredits: computed('creditsTotal', 'autoRefillAmount', function () {
    return this.autoRefillAmount;
  }),

  autoRefillPrice: computed('autoRefillAmount', function () {
    return Math.ceil(this.autoRefillAmount * 0.0006);
  }),

  autoRefillMinimumCredits: computed('creditsTotal', 'autoRefillThreshold', function () {
    return this.autoRefillThreshold;
  }),

  show: computed('subscription', function () {
    let isOrganization = this.subscription.owner.get('isOrganization');
    let isAdmin = this.subscription.owner.get('permissions').admin;
    return !(this.subscription.plan.get('isFree') || this.subscription.get('isManual') || (isOrganization && !isAdmin));
  }),

  toggleAutoRefill: task(function* (value) {
    try {
      yield this.subscription.autoRefillToggle.perform(this.subscription.owner, value);
    } catch (err) {
      this.flashes.clear();
      this.flashes.error('Something went wrong and your Auto Refill settings were not saved.');
    }
  }).restartable(),

  updateAutoRefill: task(function* () {
    try {
      yield this.subscription.autoRefillUpdate.perform(this.selectedThreshold, this.selectedAmount);
    } catch (err) {
      this.flashes.clear();
      this.flashes.error('Something went wrong and your Auto Refill settings were not saved.');
    }
  }).restartable()
});
<commit_msg>Hid autorefill switch for free plans (#2644) (#2669)<commit_after>import Component from '@ember/component';
import { reads } from '@ember/object/computed';
import { computed } from '@ember/object';
import { task } from 'ember-concurrency';
import { inject as service } from '@ember/service';

export default Component.extend({
  flashes: service(),
  accounts: service(),

  account: null,
  subscription: null,
  autoRefillEnabled: reads('subscription.autoRefillEnabled'),
  autoRefillThreshold: reads('subscription.autoRefillThreshold'),
  autoRefillAmount: reads('subscription.autoRefillAmount'),
  autoRefillThresholds: reads('subscription.autoRefillThresholds'),
  autoRefillAmounts: reads('subscription.autoRefillAmounts'),

  creditsTotal: reads('subscription.addonUsage.private.totalCredits'),

  selectedThreshold: computed('autoRefillThreshold', function () {
    return this.autoRefillThreshold;
  }),

  selectedAmount: computed('autoRefillAmount', function () {
    return this.autoRefillAmount;
  }),

  autoRefillCredits: computed('creditsTotal', 'autoRefillAmount', function () {
    return this.autoRefillAmount;
  }),

  autoRefillPrice: computed('autoRefillAmount', function () {
    return Math.ceil(this.autoRefillAmount * 0.0006);
  }),

  autoRefillMinimumCredits: computed('creditsTotal', 'autoRefillThreshold', function () {
    return this.autoRefillThreshold;
  }),

  show: computed('subscription', function () {
    let isOrganization = this.subscription.owner.get('isOrganization');
    let isAdmin = this.subscription.owner.get('permissions').admin;
    return !(this.subscription.plan.get('id') === 'free_tier_plan' || this.subscription.plan.get('id') === 'starter_plan'
        || this.subscription.get('isManual') || isOrganization && !isAdmin);
  }),

  toggleAutoRefill: task(function* (value) {
    try {
      yield this.subscription.autoRefillToggle.perform(this.subscription.owner, value);
    } catch (err) {
      this.flashes.clear();
      this.flashes.error('Something went wrong and your Auto Refill settings were not saved.');
    }
  }).restartable(),

  updateAutoRefill: task(function* () {
    try {
      yield this.subscription.autoRefillUpdate.perform(this.selectedThreshold, this.selectedAmount);
    } catch (err) {
      this.flashes.clear();
      this.flashes.error('Something went wrong and your Auto Refill settings were not saved.');
    }
  }).restartable()
});
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  page: 'cardSort1',
  cards: null,
  buckets: null,
  responses: null,
  actions: {
    dragCard(card, ops) {
      var cards = ops.target.cards;
      var buckets = ops.target.buckets;
      var buckets2 = ops.target.buckets2;
      var source;
      var target = ops.target.bucket;

      if (cards && cards.contains(card)) {
        source = cards;
      }
      for (var category in buckets) {
        if (buckets[category].contains(card)) {
          source = buckets[category];
        }
      }
      for (var group in buckets2) {
        for (var category in buckets2[group]) {
          var bucket = buckets2[group][category];
            if (bucket['cards'].contains(card)) {
             source = bucket['cards'];
          }
        }
      }
      this.sendAction('moveCard', card, source, target);
    },
    nextPage() {
      //Change page view to second card sort form
      this.set('page', 'cardSort2');
    },
    nextSection() {
      // Go to next survey section
      this.sendAction('nextSection');
    }
  }
});
<commit_msg>Add buckets2 attribute to cardsort component<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  page: 'cardSort1',
  cards: null,
  buckets: null,
  buckets2: null,
  responses: null,
  actions: {
    dragCard(card, ops) {
      var cards = ops.target.cards;
      var buckets = ops.target.buckets;
      var buckets2 = ops.target.buckets2;
      var source;
      var target = ops.target.bucket;

      if (cards && cards.contains(card)) {
        source = cards;
      }
      for (var category in buckets) {
        if (buckets[category].contains(card)) {
          source = buckets[category];
        }
      }
      for (var group in buckets2) {
        for (var category in buckets2[group]) {
          var bucket = buckets2[group][category];
            if (bucket['cards'].contains(card)) {
             source = bucket['cards'];
          }
        }
      }
      this.sendAction('moveCard', card, source, target);
    },
    nextPage() {
      //Change page view to second card sort form
      this.set('page', 'cardSort2');
    },
    nextSection() {
      // Go to next survey section
      this.sendAction('nextSection');
    }
  }
});
<|endoftext|>


<commit_before>// @flow

import React from 'react';
import Relay from 'react-relay/classic';

import Link from './link';
import Icon from '../../shared/Icon';

type Props = {
  viewer?: {
    unreadChangelogs?: {
      count: number
    }
  },
  relay: Object
};

class Footer extends React.PureComponent<Props> {
  componentDidMount() {
    this.props.relay.setVariables({ isMounted: true });
  }

  render() {
    let changelogBadge;
    // Viewer is not supplied when rendered for an anonymous user
    if (this.props.viewer && this.props.viewer.unreadChangelogs && this.props.viewer.unreadChangelogs.count > 0) {
      changelogBadge = (
        <span className={`inline-block bg-dark-gray hover-lime-child white rounded ml1 small p1 line-height-1`}>{this.props.viewer.unreadChangelogs.count}
      );
    }

    return (

          <Link href="/home">Home</Link>
          <Link href="/changelog">
            Changelog{changelogBadge}
          </Link>
          <Link href="/blog">Blog</Link>
          <Link href="/docs">Docs</Link>
          <Link href="https://github.com/buildkite/feedback/issues">Feedback</Link>
          <Link href="/privacy-policy">Privacy</Link>
          <Link href="/terms-of-service">Terms</Link>
          <Link href="mailto:support@buildkite.com">Support</Link>
          <Link href="https://buildkitestatus.com/">System Status</Link>

          <a href="http://twitter.com/buildkite" className={`btn hover-lime px1`}><Icon icon="twitter" />
          <a href="https://github.com/buildkite" className={`btn hover-lime px1`}><Icon icon="github" />

    );
  }
}

export default Relay.createContainer(Footer, {
  initialVariables: {
    isMounted: false
  },

  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        unreadChangelogs: changelogs(read: false) @include(if: $isMounted) {
          count
        }
      }
    `
  }
});
<commit_msg>Constrain the footer border to the width of `container`<commit_after>// @flow

import React from 'react';
import Relay from 'react-relay/classic';

import Link from './link';
import Icon from '../../shared/Icon';

type Props = {
  viewer?: {
    unreadChangelogs?: {
      count: number
    }
  },
  relay: Object
};

class Footer extends React.PureComponent<Props> {
  componentDidMount() {
    this.props.relay.setVariables({ isMounted: true });
  }

  render() {
    let changelogBadge;
    // Viewer is not supplied when rendered for an anonymous user
    if (this.props.viewer && this.props.viewer.unreadChangelogs && this.props.viewer.unreadChangelogs.count > 0) {
      changelogBadge = (
        <span className={`inline-block bg-dark-gray hover-lime-child white rounded ml1 small p1 line-height-1`}>{this.props.viewer.unreadChangelogs.count}
      );
    }

    return (

            <Link href="/home">Home</Link>
            <Link href="/changelog">
              Changelog{changelogBadge}
            </Link>
            <Link href="/blog">Blog</Link>
            <Link href="/docs">Docs</Link>
            <Link href="https://github.com/buildkite/feedback/issues">Feedback</Link>
            <Link href="/privacy-policy">Privacy</Link>
            <Link href="/terms-of-service">Terms</Link>
            <Link href="mailto:support@buildkite.com">Support</Link>
            <Link href="https://buildkitestatus.com/">System Status</Link>

            <a href="http://twitter.com/buildkite" className={`btn hover-lime px1`}><Icon icon="twitter" />
            <a href="https://github.com/buildkite" className={`btn hover-lime px1`}><Icon icon="github" />

    );
  }
}

export default Relay.createContainer(Footer, {
  initialVariables: {
    isMounted: false
  },

  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        unreadChangelogs: changelogs(read: false) @include(if: $isMounted) {
          count
        }
      }
    `
  }
});
<|endoftext|>


<commit_before>"use strict";

//Options still needs to be implemented.
function UFOs(container, options){

	//scene elements, I wouldn't mess with these if you are trying to work with this
	var scene, camera, renderer, map;

	//Mess with these if you don't want a full screen visualization
	var WIDTH  = window.innerWidth;
	var HEIGHT = window.innerHeight;

	//These are the map dimensions
	var MAXWIDTH = 928, MAXHEIGHT = 592;
	var cancelled = false;

	//Variables required to create UFOs
	var counter = 0;
	var ufo_geo1 = new THREE.TorusGeometry(17,3,40,50);
	var ufo_geo2 = new THREE.SphereGeometry(13,32,32);
	var ufo_material = new THREE.MeshPhongMaterial({color: 0xcccccc,reflectivity:.4});
	var ufo_material2 = new THREE.MeshPhongMaterial({color: 0xcccccc,reflectivity:.4});

	var ival;//interval val for touch listeners

	//These handle the stars
	var diskGeo = new THREE.CircleGeometry(7,40,40,40);
	var diskMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, transparent:true,opacity:1});

	//cant just use this.speed because of the calls to bind later on.
	var speed = 50;
	this.setSpeed = function(spd){speed = spd;};

	//SECTION INITIALIZATION
	function init(container) {
		scene = new THREE.Scene();
		initCamera();
		if(!window.renderer)
			initRenderer();
		renderer = window.renderer;
		initMap();
		renderer.domElement.className = "grabbable";
		container.body.appendChild(renderer.domElement);
		renderer.domElement.style.cursor="grab";
		setTimeout(function(){addMouseHandler.call(renderer.domElement);},1000);
		render();
	}

	//fires whenever the window resizes to keep the map accurate
	function resize(){
		WIDTH  = window.innerWidth;
		HEIGHT = window.innerHeight
		camera.aspect = WIDTH/HEIGHT;
		camera.updateProjectionMatrix();
		renderer.setSize(WIDTH, HEIGHT);
	}

	function initCamera() {
		camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 4000);
		camera.position.set(0,-200,600);
		camera.lookAt(scene.position);
	}

	//Prevents excessive WebGLRenderer instances
	function initRenderer() {

		renderer = new THREE.WebGLRenderer({ antialias: true });
		renderer.setClearColor(0x000000);
		renderer.setPixelRatio( window.devicePixelRatio );

		renderer.setSize(WIDTH, HEIGHT);
		window.renderer = renderer;
	}

	function initMap() {
		var loader = new THREE.TextureLoader();

		var texture = loader.load("img/usa.jpg");
		var material = new THREE.MeshPhongMaterial({map:texture});
		material.bumpMap =texture;
		material.bumpScale = 22;

		map = new THREE.Mesh(new THREE.CubeGeometry(MAXWIDTH,MAXHEIGHT, 2), material);
		var light = new THREE.DirectionalLight( 0xffffff );
		light.position.set( 1000, 1000, 1000);
		light.castShadow = true;
		map.receiveShadow = true;
		scene.add(light);
		scene.add(map);
	}
	// END INITIALIZATION

	function addUFO(x,y){
		if(cancelled){
			return;
		}
		counter++;
      		var ufo = new THREE.Mesh(ufo_geo1,ufo_material);
		var sub_ufo = new THREE.Mesh(ufo_geo2,ufo_material2);
		ufo.add(sub_ufo);
      		ufo.castShadow = true;
      		ufo.receiveShadow = true;
		ufo.name = counter.toString();
		ufo.isUFO = true;
		map.add(ufo);
		ufo.position.set(-928/2 +x,592/2 -y,400);
		loopWrapper(animateUFO.bind(ufo));
	}

	//Adds a ufo at a certain percentage of the way across the screen
	function addUFOPercent(x,y){
		addUFO(x*MAXWIDTH, y*MAXHEIGHT);
	}

	//loops for animation until the function returns false.
	function loopWrapper(callback){
			if(cancelled){
					return;
			}
			if(callback()){
					setTimeout(function(){loopWrapper(callback);},Math.floor(20*((150-(speed))/150)));
			}
	}

	//transitions a ufo in.
	function animateUFO(){
		this.position.z-=3;

		if(this.position.z<=130){
				var disk = new THREE.Mesh(diskGeo,diskMaterial.clone());
				disk.position.copy(this.position);

				map.add(disk);
				var tempJson = {
						disk:disk,
						ufo:this,
						counter:1000
				};

				loopWrapper(castBeam.bind(tempJson));
				return false;
		}
		return true;
	}

	//casts stars onto the map.
	function castBeam(){
				this.counter++;
				if(this.counter > 5){
						var disk = new THREE.Mesh(diskGeo,diskMaterial);
						disk.position.copy(this.ufo.position);
						map.add(disk);
						loopWrapper(castDown.bind(disk));
						this.counter = 0;
				}

				this.disk.position.z-=2;
				if(this.disk.position.z <= 3){
						var fun = remove.bind(this.ufo);
						setTimeout(function(){loopWrapper(fun);},Math.floor(200*(150-speed)/150));
						loopWrapper(fadeOut.bind(this.disk));
						return false;
				}
				return true;
	}
	function castDown(){
			this.position.z-=2;
			if(this.position.z <=3){
				map.remove(this);
				return false;
			}
			return true;
	}

	function fadeOut(){

		if(this.material.opacity <= .01){
			map.remove(this);
			return false;
		}
		else{
			this.material.opacity-=.001;
		}
			return true;
	}

	//fly away and remove.
	function remove(){
				this.position.z+=5;
				if(this.position.z >=700){
					map.remove(this);
					return false;
				}
				return true;
	}

	//This removes all children.
	function resetStars(){
		//this clears nested children too, kind of a funky behavior but just had to deal with it.
		//Threejs struggles with removing objects.  Sometimes you have to try a few times to get it to work.
		//This probably has to do with the fact that these objects still exist in the event loop due to my animation implementation.
		cancelled = true;
		for(var i = map.children.length; i >= 0; i--){
			map.remove(map.children[i])
		}
		setTimeout(function(){cancelled = false;},Math.floor(40*((150-(speed))/150)));

	}

	function render(){
                renderer.render(scene, camera);
                requestAnimationFrame(render);
	}

	//Mouse handlers
	//This section handles mouse events for rotation.  I kept the variables down here so that they are easier to keep track of.
	//This is all a closure, so these functions aren't available outside which is good.
	function addMouseHandler() {

			var mouseDown = false,mouseX,mouseY;
			function onMouseMove(e) {
			  e.preventDefault();

			  var deltaX = e.clientX - mouseX, deltaY = e.clientY - mouseY;
			  mouseX = e.clientX;
			  mouseY = e.clientY;

			  if (mouseDown) {
					rotateScene(deltaX);
					moveScene(deltaY);
			  }
			}

			function onMouseUp(evt) {
				evt.preventDefault();
				mouseDown = false;
			}

			function onMouseDown(evt){
				evt.preventDefault();
				mouseDown = true;
			}

			var touchX, touchY, touched = false,touched_first = false;

		this.addEventListener("touchstart", function(e){
			if(!touched_first){
				setInterval(touchHandler,20);
				touched_first = true;
			}
			touched = true;
			touchX= e.touches[0].clientX;
			touchY = e.touches[0].clientY;
			e.preventDefault();
		}, true);

		this.addEventListener("touchmove",function(e){
			touchX= e.touches[0].clientX;
			touchY = e.touches[0].clientY;
			e.preventDefault();
		});

		this.addEventListener("touchend", function(e){
			touched = false;
			e.preventDefault();
		}, true);

		function touchHandler(){
			if(touched){
				rotateScene(5 * (touchX - (WIDTH/2))/(WIDTH/2));
				moveScene(-5 * (touchY - HEIGHT/2)/(HEIGHT/2));
			}
		}

		//TODO implement zoom
		function wheelHandler(e){

		}
		this.addEventListener("wheel",wheelHandler,false);

		this.addEventListener('mousemove',onMouseMove,false);

		this.addEventListener('mousedown', onMouseDown,false);

		this.addEventListener('mouseup', onMouseUp,false);

	}

	//This is outside of addMouseHandler because I want these to be publicly available for people to add custom controls if they so desire.
	function rotateScene(deltaX){
			map.rotation.z-= deltaX/100;
	}
	function moveScene(deltaY) {
		if((camera.position.z > 300 || deltaY > 0) && (camera.position.z < 700 || deltaY < 0)){
			camera.position.z += deltaY;
			camera.position.y += deltaY*1.5;
			camera.rotation.x-=deltaY/360;
		}
	}

		//Call init and define public functions.
		init(container);
		moveScene(-50);
		this.addUFO = addUFO;
		this.resize = resize;
		this.addUFOPercent = addUFOPercent;
		this.resetStars = resetStars;
		this.rotateScene = rotateScene;
		this.moveScene = moveScene;
		this.destroy = function(){renderer.domElement.parentNode.removeChild(renderer.domElement);}
}
<commit_msg>slightly larger spheres to prevent the tiny gap in the UFO's end geometry<commit_after>"use strict";

//Options still needs to be implemented.
function UFOs(container, options){

	//scene elements, I wouldn't mess with these if you are trying to work with this
	var scene, camera, renderer, map;

	//Mess with these if you don't want a full screen visualization
	var WIDTH  = window.innerWidth;
	var HEIGHT = window.innerHeight;

	//These are the map dimensions
	var MAXWIDTH = 928, MAXHEIGHT = 592;
	var cancelled = false;

	//Variables required to create UFOs
	var counter = 0;
	var ufo_geo1 = new THREE.TorusGeometry(17,3,40,50);
	var ufo_geo2 = new THREE.SphereGeometry(14,32,32);
	var ufo_material = new THREE.MeshPhongMaterial({color: 0xcccccc,reflectivity:.4});
	var ufo_material2 = new THREE.MeshPhongMaterial({color: 0xcccccc,reflectivity:.4});

	var ival;//interval val for touch listeners

	//These handle the stars
	var diskGeo = new THREE.CircleGeometry(7,40,40,40);
	var diskMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, transparent:true,opacity:1});

	//cant just use this.speed because of the calls to bind later on.
	var speed = 50;
	this.setSpeed = function(spd){speed = spd;};

	//SECTION INITIALIZATION
	function init(container) {
		scene = new THREE.Scene();
		initCamera();
		if(!window.renderer)
			initRenderer();
		renderer = window.renderer;
		initMap();
		renderer.domElement.className = "grabbable";
		container.body.appendChild(renderer.domElement);
		renderer.domElement.style.cursor="grab";
		setTimeout(function(){addMouseHandler.call(renderer.domElement);},1000);
		render();
	}

	//fires whenever the window resizes to keep the map accurate
	function resize(){
		WIDTH  = window.innerWidth;
		HEIGHT = window.innerHeight
		camera.aspect = WIDTH/HEIGHT;
		camera.updateProjectionMatrix();
		renderer.setSize(WIDTH, HEIGHT);
	}

	function initCamera() {
		camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 4000);
		camera.position.set(0,-200,600);
		camera.lookAt(scene.position);
	}

	//Prevents excessive WebGLRenderer instances
	function initRenderer() {

		renderer = new THREE.WebGLRenderer({ antialias: true });
		renderer.setClearColor(0x000000);
		renderer.setPixelRatio( window.devicePixelRatio );

		renderer.setSize(WIDTH, HEIGHT);
		window.renderer = renderer;
	}

	function initMap() {
		var loader = new THREE.TextureLoader();

		var texture = loader.load("img/usa.jpg");
		var material = new THREE.MeshPhongMaterial({map:texture});
		material.bumpMap =texture;
		material.bumpScale = 22;

		map = new THREE.Mesh(new THREE.CubeGeometry(MAXWIDTH,MAXHEIGHT, 2), material);
		var light = new THREE.DirectionalLight( 0xffffff );
		light.position.set( 1000, 1000, 1000);
		light.castShadow = true;
		map.receiveShadow = true;
		scene.add(light);
		scene.add(map);
	}
	// END INITIALIZATION

	function addUFO(x,y){
		if(cancelled){
			return;
		}
		counter++;
      		var ufo = new THREE.Mesh(ufo_geo1,ufo_material);
		var sub_ufo = new THREE.Mesh(ufo_geo2,ufo_material2);
		ufo.add(sub_ufo);
      		ufo.castShadow = true;
      		ufo.receiveShadow = true;
		ufo.name = counter.toString();
		ufo.isUFO = true;
		map.add(ufo);
		ufo.position.set(-928/2 +x,592/2 -y,400);
		loopWrapper(animateUFO.bind(ufo));
	}

	//Adds a ufo at a certain percentage of the way across the screen
	function addUFOPercent(x,y){
		addUFO(x*MAXWIDTH, y*MAXHEIGHT);
	}

	//loops for animation until the function returns false.
	function loopWrapper(callback){
			if(cancelled){
					return;
			}
			if(callback()){
					setTimeout(function(){loopWrapper(callback);},Math.floor(20*((150-(speed))/150)));
			}
	}

	//transitions a ufo in.
	function animateUFO(){
		this.position.z-=3;

		if(this.position.z<=130){
				var disk = new THREE.Mesh(diskGeo,diskMaterial.clone());
				disk.position.copy(this.position);

				map.add(disk);
				var tempJson = {
						disk:disk,
						ufo:this,
						counter:1000
				};

				loopWrapper(castBeam.bind(tempJson));
				return false;
		}
		return true;
	}

	//casts stars onto the map.
	function castBeam(){
				this.counter++;
				if(this.counter > 5){
						var disk = new THREE.Mesh(diskGeo,diskMaterial);
						disk.position.copy(this.ufo.position);
						map.add(disk);
						loopWrapper(castDown.bind(disk));
						this.counter = 0;
				}

				this.disk.position.z-=2;
				if(this.disk.position.z <= 3){
						var fun = remove.bind(this.ufo);
						setTimeout(function(){loopWrapper(fun);},Math.floor(200*(150-speed)/150));
						loopWrapper(fadeOut.bind(this.disk));
						return false;
				}
				return true;
	}
	function castDown(){
			this.position.z-=2;
			if(this.position.z <=3){
				map.remove(this);
				return false;
			}
			return true;
	}

	function fadeOut(){

		if(this.material.opacity <= .01){
			map.remove(this);
			return false;
		}
		else{
			this.material.opacity-=.001;
		}
			return true;
	}

	//fly away and remove.
	function remove(){
				this.position.z+=5;
				if(this.position.z >=700){
					map.remove(this);
					return false;
				}
				return true;
	}

	//This removes all children.
	function resetStars(){
		//this clears nested children too, kind of a funky behavior but just had to deal with it.
		//Threejs struggles with removing objects.  Sometimes you have to try a few times to get it to work.
		//This probably has to do with the fact that these objects still exist in the event loop due to my animation implementation.
		cancelled = true;
		for(var i = map.children.length; i >= 0; i--){
			map.remove(map.children[i])
		}
		setTimeout(function(){cancelled = false;},Math.floor(40*((150-(speed))/150)));

	}

	function render(){
                renderer.render(scene, camera);
                requestAnimationFrame(render);
	}

	//Mouse handlers
	//This section handles mouse events for rotation.  I kept the variables down here so that they are easier to keep track of.
	//This is all a closure, so these functions aren't available outside which is good.
	function addMouseHandler() {

			var mouseDown = false,mouseX,mouseY;
			function onMouseMove(e) {
			  e.preventDefault();

			  var deltaX = e.clientX - mouseX, deltaY = e.clientY - mouseY;
			  mouseX = e.clientX;
			  mouseY = e.clientY;

			  if (mouseDown) {
					rotateScene(deltaX);
					moveScene(deltaY);
			  }
			}

			function onMouseUp(evt) {
				evt.preventDefault();
				mouseDown = false;
			}

			function onMouseDown(evt){
				evt.preventDefault();
				mouseDown = true;
			}

			var touchX, touchY, touched = false,touched_first = false;

		this.addEventListener("touchstart", function(e){
			if(!touched_first){
				setInterval(touchHandler,20);
				touched_first = true;
			}
			touched = true;
			touchX= e.touches[0].clientX;
			touchY = e.touches[0].clientY;
			e.preventDefault();
		}, true);

		this.addEventListener("touchmove",function(e){
			touchX= e.touches[0].clientX;
			touchY = e.touches[0].clientY;
			e.preventDefault();
		});

		this.addEventListener("touchend", function(e){
			touched = false;
			e.preventDefault();
		}, true);

		function touchHandler(){
			if(touched){
				rotateScene(5 * (touchX - (WIDTH/2))/(WIDTH/2));
				moveScene(-5 * (touchY - HEIGHT/2)/(HEIGHT/2));
			}
		}

		//TODO implement zoom
		function wheelHandler(e){

		}
		this.addEventListener("wheel",wheelHandler,false);

		this.addEventListener('mousemove',onMouseMove,false);

		this.addEventListener('mousedown', onMouseDown,false);

		this.addEventListener('mouseup', onMouseUp,false);

	}

	//This is outside of addMouseHandler because I want these to be publicly available for people to add custom controls if they so desire.
	function rotateScene(deltaX){
			map.rotation.z-= deltaX/100;
	}
	function moveScene(deltaY) {
		if((camera.position.z > 300 || deltaY > 0) && (camera.position.z < 700 || deltaY < 0)){
			camera.position.z += deltaY;
			camera.position.y += deltaY*1.5;
			camera.rotation.x-=deltaY/360;
		}
	}

		//Call init and define public functions.
		init(container);
		moveScene(-50);
		this.addUFO = addUFO;
		this.resize = resize;
		this.addUFOPercent = addUFOPercent;
		this.resetStars = resetStars;
		this.rotateScene = rotateScene;
		this.moveScene = moveScene;
		this.destroy = function(){renderer.domElement.parentNode.removeChild(renderer.domElement);}
}
<|endoftext|>


<commit_before>function ulam(container, width, height, cubeWidth, count){
	container.innerHTML = "";//clear container
	var canvas = document.createElement("canvas"); //create canvas
	var ctx = canvas.getContext("2d");

	var	dir = "right"; //program direction
	var turn = 0; //turns passed in that direction
	var turns = 2; //total turns shouldve pass
	var turnRow = 0; //all turns should pass twice, for example right: 2, down: 2 left: 3, up: 3, right: 4...
	var m;//for leastFactor
	ctx.beginPath();
	var cubeWidth = parseInt(document.getElementById("cubeWidth").value, 10);//width of all prime cubes
	var count = parseInt(document.getElementById("count").value,10); //count of numbers should program check, not prime count
	canvas.width = parseInt(document.getElementById("width").value,10);
	canvas.height = parseInt(document.getElementById("height").value,10);
	ctx.fillStyle = "black";

	//ctx.rect(canvas.width / 2, canvas.height / 2, cubeWidth, cubeWidth);
	ctx.rect(canvas.width / 2 + cubeWidth,canvas.height / 2, cubeWidth, cubeWidth); //fill number 2
	ctx.rect(canvas.width / 2 + cubeWidth,canvas.height / 2 - cubeWidth,cubeWidth,cubeWidth); //fill number 3
	curLoc = [canvas.width / 2 + cubeWidth,canvas.height / 2 - cubeWidth];//start with number 4

	// I've used a fast prime function found from http://www.javascripter.net/faq/numberisprime.htm
	isPrime = function(n) {
		if (n%1 || n<2) return false;
		if (n==leastFactor(n)) return true;
		return false;
	}

	leastFactor = function(n){
		if (isNaN(n) || !isFinite(n)) return NaN;
		if (n==0) return 0;
		if (n%1 || n*n<2) return 1;
		if (n%2==0) return 2;
		if (n%3==0) return 3;
		if (n%5==0) return 5;
		m = Math.sqrt(n);
		for (var i=7;i<=m;i+=30) {
			if (n%i==0)      return i;
			if (n%(i+4)==0)  return i+4;
			if (n%(i+6)==0)  return i+6;
			if (n%(i+10)==0) return i+10;
			if (n%(i+12)==0) return i+12;
			if (n%(i+16)==0) return i+16;
			if (n%(i+22)==0) return i+22;
			if (n%(i+24)==0) return i+24;
		}
		return n;
	}
	for(i = 4; i <= count; i++){
		switch(dir){
			case "right":
				//if we are going into right, we should increment turn
				turn++;
				if(turn == turns) {
					// if turn is equal to max turns, turnrow should increment
					//if turnrow equals to 2, turns should increment
					turnRow ++;
					dir = "down";
					turn = 0;
					if(turnRow == 2){
						turnRow = 0;
						turns++;
					}
				}
				curLoc[0] -= cubeWidth;//
				if(isPrime(i)){
					//if i is prime, fill!
					ctx.rect(curLoc[0],curLoc[1],cubeWidth,cubeWidth);
				}
			break;
			case "down":
				turn++;
				if(turn == turns) {
					dir = "left";
					turn = 0;
					turnRow ++;
					if(turnRow == 2){
						turnRow = 0;
						turns++;
					}
				}
				curLoc[1] += cubeWidth;
				if(isPrime(i)){
					ctx.rect(curLoc[0],curLoc[1],cubeWidth,cubeWidth);
				}
			break;
			case "left":
				turn++;
				if(turn == turns) {
					dir = "up";
					turn = 0;
					turnRow ++;
					if(turnRow == 2){
						turnRow = 0;
						turns++;
					}
				}
				curLoc[0] += cubeWidth;
				if(isPrime(i)){
					ctx.rect(curLoc[0],curLoc[1],cubeWidth,cubeWidth);
				}
			break;
			case "up":
				turn++;
				if(turn == turns) {
					dir = "right";
					turn = 0;
					turnRow ++;
					if(turnRow == 2){
						turnRow = 0;
						turns++;
					}
				}
				curLoc[1] -= cubeWidth;
				if(isPrime(i)){
					ctx.rect(curLoc[0],curLoc[1],cubeWidth,cubeWidth);
				}
			break;
		}
	}
	ctx.fill(); //fill up the board ! yay
	container.appendChild(canvas); //append canvas to container
}<commit_msg>global fix<commit_after>function ulam(container, width, height, cubeWidth, count, color){
	container.innerHTML = "";//clear container
	var canvas = document.createElement("canvas"); //create canvas
	var ctx = canvas.getContext("2d");

	var	dir = "right"; //program direction
	var turn = 0; //turns passed in that direction
	var turns = 2; //total turns shouldve pass
	var turnRow = 0; //all turns should pass twice, for example right: 2, down: 2 left: 3, up: 3, right: 4...
	var m;//for leastFactor
	ctx.beginPath();
	var cubeWidth = cubeWidth;
	var count = count;
	canvas.width = width;
	canvas.height = height;
	ctx.fillStyle = color;

	//ctx.rect(canvas.width / 2, canvas.height / 2, cubeWidth, cubeWidth);
	ctx.rect(canvas.width / 2 + cubeWidth,canvas.height / 2, cubeWidth, cubeWidth); //fill number 2
	ctx.rect(canvas.width / 2 + cubeWidth,canvas.height / 2 - cubeWidth,cubeWidth,cubeWidth); //fill number 3
	curLoc = [canvas.width / 2 + cubeWidth,canvas.height / 2 - cubeWidth];//start with number 4

	// I've used a fast prime function found from http://www.javascripter.net/faq/numberisprime.htm
	isPrime = function(n) {
		if (n%1 || n<2) return false;
		if (n==leastFactor(n)) return true;
		return false;
	}

	leastFactor = function(n){
		if (isNaN(n) || !isFinite(n)) return NaN;
		if (n==0) return 0;
		if (n%1 || n*n<2) return 1;
		if (n%2==0) return 2;
		if (n%3==0) return 3;
		if (n%5==0) return 5;
		m = Math.sqrt(n);
		for (var i=7;i<=m;i+=30) {
			if (n%i==0)      return i;
			if (n%(i+4)==0)  return i+4;
			if (n%(i+6)==0)  return i+6;
			if (n%(i+10)==0) return i+10;
			if (n%(i+12)==0) return i+12;
			if (n%(i+16)==0) return i+16;
			if (n%(i+22)==0) return i+22;
			if (n%(i+24)==0) return i+24;
		}
		return n;
	}
	for(i = 4; i <= count; i++){
		switch(dir){
			case "right":
				//if we are going into right, we should increment turn
				turn++;
				if(turn == turns) {
					// if turn is equal to max turns, turnrow should increment
					//if turnrow equals to 2, turns should increment
					turnRow ++;
					dir = "down";
					turn = 0;
					if(turnRow == 2){
						turnRow = 0;
						turns++;
					}
				}
				curLoc[0] -= cubeWidth;//
				if(isPrime(i)){
					//if i is prime, fill!
					ctx.rect(curLoc[0],curLoc[1],cubeWidth,cubeWidth);
				}
			break;
			case "down":
				turn++;
				if(turn == turns) {
					dir = "left";
					turn = 0;
					turnRow ++;
					if(turnRow == 2){
						turnRow = 0;
						turns++;
					}
				}
				curLoc[1] += cubeWidth;
				if(isPrime(i)){
					ctx.rect(curLoc[0],curLoc[1],cubeWidth,cubeWidth);
				}
			break;
			case "left":
				turn++;
				if(turn == turns) {
					dir = "up";
					turn = 0;
					turnRow ++;
					if(turnRow == 2){
						turnRow = 0;
						turns++;
					}
				}
				curLoc[0] += cubeWidth;
				if(isPrime(i)){
					ctx.rect(curLoc[0],curLoc[1],cubeWidth,cubeWidth);
				}
			break;
			case "up":
				turn++;
				if(turn == turns) {
					dir = "right";
					turn = 0;
					turnRow ++;
					if(turnRow == 2){
						turnRow = 0;
						turns++;
					}
				}
				curLoc[1] -= cubeWidth;
				if(isPrime(i)){
					ctx.rect(curLoc[0],curLoc[1],cubeWidth,cubeWidth);
				}
			break;
		}
	}
	ctx.fill(); //fill up the board ! yay
	container.appendChild(canvas); //append canvas to container
}<|endoftext|>


<commit_before>'use strict';

var Poll = require('../models/polls.js');
var PollOption = require('../models/pollOptions.js');
var Vote = require('../models/votes.js');
var ip = require("ip");

function pollHandler () {

	this.getPolls = function (callback) {
	    Poll
	        .find({active: true})
					.populate('author')
					.populate({
						path: "options",
						model: "PollOption",
						populate: {
							path: 'votes',
							model: 'Vote'
						}
					})
	        .exec(function (err, result) {
	                if (err) return callback(err);
                  callback(err, result);
	            });
	};

  this.addPoll = function (user, poll, callback) {
		// Date to use many times
		let now = new Date();

		// Populate Poll Object
    let newPoll = Poll.newInstance(user._id, poll.title);

		let allPollOptionsCreated = [];
    for (let op in poll.options){
			// Populate Poll Options
			let newPollOption = PollOption.newInstance(newPoll._id, user._id, poll.options[op]);

			// save option in poll
			newPoll.options.push(newPollOption._id);

			// ready with this option
			allPollOptionsCreated.push(newPollOption);
    }

		// Save Poll Options
		PollOption.insertMany(allPollOptionsCreated, (err, result) => {
			if (err) return callback(err);
			// Save Poll
			newPoll.save(function(err, result){
				if (err) return callback(err);
				return callback(false, result);
			});
		});
  };

  this.getPollsByUserId = function(userId, callback){
    Poll
        .find({author: userId, active: true})
				.populate('author')
				.populate({
					path: "options",
					model: "PollOption",
					populate: {
						path: 'votes',
						model: 'Vote'
					}
				})
        .exec(function (err, result) {
                if (err) return callback(err);
								callback(false, result);
            });
  }
  this.getPollById = function(id, callback){
    Poll
        .findOne({_id: id, active:true})
				.populate('author')
				.populate({
					path: "options",
					model: "PollOption",
					populate: {
						path: 'votes',
						model: 'Vote'
					}
				})
        .exec(function (err, result) {
                if (err) return callback(err);
								callback(false, result);
            });
  }
	this.addVote = function(optionId, userId, voterIp, callback){
		PollOption
				.findById(optionId)
				.exec(function (err, pollOption) {
								if (err) return callback(err);
								if (!pollOption) return callback(true);

								// Create and fill vote
								let vote = Vote.newInstance(optionId, userId, voterIp);

								// Save vote
								vote.save(function(err, vote){
									if (err) callback(err);
									// Add vote to option
									pollOption.votes.push(vote._id);
									pollOption.save((err, pollOption) => {
										if (err) return callback(err);
										callback(false, pollOption);
									});
								});
						});
	},
	this.addOption = function(poll, optionText, userId, callback){
		// If option text already exists, error
		let found = poll.options.find(o => o.displayName == optionText);
		if (found) return callback("The option already exists");

		// all is ok. let's create the option
		let newPollOption = PollOption.newInstance(poll._id, userId, optionText);
		//@TODO if poll.AUTHOR != userId: state="pending"
		// until poll author activate it or not
		//newPollOption.state = "pending";

		newPollOption.save(function(err, pollOption){
			if (err) return callback(err);
			poll.options.push(pollOption._id);
			poll.save((err, poll) => {
				if (err) return callback(err);
				return callback(false, pollOption);
			});
		});
	},

	/*
	Remove Poll:
	It receives poll to be removed
	and user id who requested te removal
	It removes poll, options of the poll and votes from each option
	*/
	this.removePoll = (pollToRemove, userId, callback) => {
		console.log("Poll to be removed: ", pollToRemove._id, "by", pollToRemove.author.displayName);

		// In case given poll is populated or not
		let pollAuthor = pollToRemove.author._id || pollToRemove.author;
		let optionsToRemove = pollToRemove.options.map(o => o._id || o);
		console.log("Options to be removed: ", optionsToRemove);

		// Only author of the poll can remove the poll
		if (!pollAuthor.equals(userId)) return callback("Error: You have no permissions to delete this poll");

		// Get options to remove
		PollOption
			.find({_id: {$in: optionsToRemove}})
			.exec((err, optionDocs) => {
				if (err) return callback("Error: On gathering poll options from database. Please try again later.");
				optionDocs.forEach(o => {

					// Get votes to remove
					Vote
						.update({_id: {$in: o.votes}}, {state: "inactive"})
						.exec((err, res) => {
							if (err) return callback("Error: on removing votes. Please try again later.");
							o.state = "inactive";
							o.save( (err, result) => {
								if (err) return callback(err);
								if (!result) return callback("Error: Unexpected failure in saving a deleted option. Please, try again later.");
								console.log("Finish removing Option", result.displayName);
							});
						});
				});
			});

			// fINALLY, REMOVE POLL
			//@TODO Promises: only remove pollToRemove when all options finished removing succesfully
			pollToRemove.active = false;
			pollToRemove.save( (err, result) => {
				if (err) return callback(err);
				if (!result) return callback("Error: Unexpected failure in saving deleted poll. Please, try again Later.");
				console.log("Finish removing poll");
				return callback(false, result);
			});
			/*
		pollToRemove.options.forEach(idOptionToRemove => {
			console.log("Option to be removed: ", idOptionToRemove);
			PollOption
				.findById(idOptionToRemove)
				.exec((err, optionToRemove) => {
					if (err) return callback("Error: On removing options. Please try again later.");
					optionToRemove.votes.forEach(idVote => {
						console.log("Vote to be removed: ", idVote);
						Vote
							.findById(idVote)
							.exec((err, voteToRemove) => {
								console.log("Vote searched vs received: ", idVote, voteToRemove);
								if (err) return callback("Error: on removing votes. Please try again later.");
								voteToRemove.state = "inactive";
								voteToRemove.save( (err, result) => {
									if (err) return callback(err);
									if (!result) return callback("Error: Unexpected failure in saving a deleted vote. Please, try again later.");
									console.log("Finish removing vote", result._id);
								});
							})
					});
					//@TODO Promises: only remove PollOption when all votes finished removing succesfully
					optionToRemove.state = "inactive";
					optionToRemove.save( (err, result) => {
						if (err) return callback(err);
						if (!result) return callback("Error: Unexpected failure in saving a deleted option. Please, try again later.");
						console.log("Finish removing Option", result.displayName);
					});
				});
			});
			//@TODO Promises: only remove pollToRemove when all options finished removing succesfully
			pollToRemove.active = false;
			pollToRemove.save( (err, result) => {
				if (err) return callback(err);
				if (!result) return callback("Error: Unexpected failure in saving deleted poll. Please, try again Later.");
				console.log("Finish removing poll");
				return callback(false, result);
			});
			*/
	},

	this.getAllVotesFromPoll = (pollId, callback) => {
		this.getPollById(pollId, (err, poll) => {
			if (err) return callback(err);
			let pollVotes = []
			let allOp = poll.options.toObject();
			for (let i in allOp){
				let allVotes = allOp[i].votes.toObject();
				for (let j in allVotes){
					pollVotes.push(allVotes[j])
				}
			}
			callback(false, pollVotes);
		});
	},
	this.getAllVotersIdFromPoll = (pollId, callback) => {
		this.getAllVotesFromPoll(pollId, (err, votes) => {
			if (err) return callback(err);
			let out = votes.reduce((votersId, vote) => {
				votersId.push(vote.voter);
				return votersId;
			}, []);
			callback(false, out);
		})
	},
	this.hasVoted = (poll, userId, userIp, callback) => {
		// the options I want the votes to be in
		let allPollOptions = poll.options;
		let toSearch = {
			"pollOption": {$in: allPollOptions}
		};

		// if is an authenticated user, search by user id
		if (userId) {
			toSearch["voter"] = userId;
		} else {
			// if not authenticated search by ip
			toSearch["_voterIp_buf"] = ip.toBuffer(userIp)
		}

		// Search votes under given conditions
		Vote
			.find(toSearch)
			.exec((err, votesGivenByThisUser) => {
				if (err) return callback(err);

				// HASVOTED is true when array is NOT empty
				callback(false, votesGivenByThisUser.length > 0);
			});
	}
}

module.exports = pollHandler;
<commit_msg>forgot to delete unnecesary lines of code<commit_after>'use strict';

var Poll = require('../models/polls.js');
var PollOption = require('../models/pollOptions.js');
var Vote = require('../models/votes.js');
var ip = require("ip");

function pollHandler () {

	this.getPolls = function (callback) {
	    Poll
	        .find({active: true})
					.populate('author')
					.populate({
						path: "options",
						model: "PollOption",
						populate: {
							path: 'votes',
							model: 'Vote'
						}
					})
	        .exec(function (err, result) {
	                if (err) return callback(err);
                  callback(err, result);
	            });
	};

  this.addPoll = function (user, poll, callback) {
		// Date to use many times
		let now = new Date();

		// Populate Poll Object
    let newPoll = Poll.newInstance(user._id, poll.title);

		let allPollOptionsCreated = [];
    for (let op in poll.options){
			// Populate Poll Options
			let newPollOption = PollOption.newInstance(newPoll._id, user._id, poll.options[op]);

			// save option in poll
			newPoll.options.push(newPollOption._id);

			// ready with this option
			allPollOptionsCreated.push(newPollOption);
    }

		// Save Poll Options
		PollOption.insertMany(allPollOptionsCreated, (err, result) => {
			if (err) return callback(err);
			// Save Poll
			newPoll.save(function(err, result){
				if (err) return callback(err);
				return callback(false, result);
			});
		});
  };

  this.getPollsByUserId = function(userId, callback){
    Poll
        .find({author: userId, active: true})
				.populate('author')
				.populate({
					path: "options",
					model: "PollOption",
					populate: {
						path: 'votes',
						model: 'Vote'
					}
				})
        .exec(function (err, result) {
                if (err) return callback(err);
								callback(false, result);
            });
  }
  this.getPollById = function(id, callback){
    Poll
        .findOne({_id: id, active:true})
				.populate('author')
				.populate({
					path: "options",
					model: "PollOption",
					populate: {
						path: 'votes',
						model: 'Vote'
					}
				})
        .exec(function (err, result) {
                if (err) return callback(err);
								callback(false, result);
            });
  }
	this.addVote = function(optionId, userId, voterIp, callback){
		PollOption
				.findById(optionId)
				.exec(function (err, pollOption) {
								if (err) return callback(err);
								if (!pollOption) return callback(true);

								// Create and fill vote
								let vote = Vote.newInstance(optionId, userId, voterIp);

								// Save vote
								vote.save(function(err, vote){
									if (err) callback(err);
									// Add vote to option
									pollOption.votes.push(vote._id);
									pollOption.save((err, pollOption) => {
										if (err) return callback(err);
										callback(false, pollOption);
									});
								});
						});
	},
	this.addOption = function(poll, optionText, userId, callback){
		// If option text already exists, error
		let found = poll.options.find(o => o.displayName == optionText);
		if (found) return callback("The option already exists");

		// all is ok. let's create the option
		let newPollOption = PollOption.newInstance(poll._id, userId, optionText);
		//@TODO if poll.AUTHOR != userId: state="pending"
		// until poll author activate it or not
		//newPollOption.state = "pending";

		newPollOption.save(function(err, pollOption){
			if (err) return callback(err);
			poll.options.push(pollOption._id);
			poll.save((err, poll) => {
				if (err) return callback(err);
				return callback(false, pollOption);
			});
		});
	},

	/*
	Remove Poll:
	It receives poll to be removed
	and user id who requested te removal
	It removes poll, options of the poll and votes from each option
	*/
	this.removePoll = (pollToRemove, userId, callback) => {
		console.log("Poll to be removed: ", pollToRemove._id, "by", pollToRemove.author.displayName);

		// In case given poll is populated or not
		let pollAuthor = pollToRemove.author._id || pollToRemove.author;
		let optionsToRemove = pollToRemove.options.map(o => o._id || o);
		console.log("Options to be removed: ", optionsToRemove);

		// Only author of the poll can remove the poll
		if (!pollAuthor.equals(userId)) return callback("Error: You have no permissions to delete this poll");

		// Get options to remove
		PollOption
			.find({_id: {$in: optionsToRemove}})
			.exec((err, optionDocs) => {
				if (err) return callback("Error: On gathering poll options from database. Please try again later.");
				optionDocs.forEach(o => {

					// Get votes to remove
					Vote
						.update({_id: {$in: o.votes}}, {state: "inactive"})
						.exec((err, res) => {
							if (err) return callback("Error: on removing votes. Please try again later.");
							o.state = "inactive";
							o.save( (err, result) => {
								if (err) return callback(err);
								if (!result) return callback("Error: Unexpected failure in saving a deleted option. Please, try again later.");
								console.log("Finish removing Option", result.displayName);
							});
						});
				});
			});

			// fINALLY, REMOVE POLL
			//@TODO Promises: only remove pollToRemove when all options finished removing succesfully
			pollToRemove.active = false;
			pollToRemove.save( (err, result) => {
				if (err) return callback(err);
				if (!result) return callback("Error: Unexpected failure in saving deleted poll. Please, try again Later.");
				console.log("Finish removing poll");
				return callback(false, result);
			});
	},

	this.getAllVotesFromPoll = (pollId, callback) => {
		this.getPollById(pollId, (err, poll) => {
			if (err) return callback(err);
			let pollVotes = []
			let allOp = poll.options.toObject();
			for (let i in allOp){
				let allVotes = allOp[i].votes.toObject();
				for (let j in allVotes){
					pollVotes.push(allVotes[j])
				}
			}
			callback(false, pollVotes);
		});
	},
	this.getAllVotersIdFromPoll = (pollId, callback) => {
		this.getAllVotesFromPoll(pollId, (err, votes) => {
			if (err) return callback(err);
			let out = votes.reduce((votersId, vote) => {
				votersId.push(vote.voter);
				return votersId;
			}, []);
			callback(false, out);
		})
	},
	this.hasVoted = (poll, userId, userIp, callback) => {
		// the options I want the votes to be in
		let allPollOptions = poll.options;
		let toSearch = {
			"pollOption": {$in: allPollOptions}
		};

		// if is an authenticated user, search by user id
		if (userId) {
			toSearch["voter"] = userId;
		} else {
			// if not authenticated search by ip
			toSearch["_voterIp_buf"] = ip.toBuffer(userIp)
		}

		// Search votes under given conditions
		Vote
			.find(toSearch)
			.exec((err, votesGivenByThisUser) => {
				if (err) return callback(err);

				// HASVOTED is true when array is NOT empty
				callback(false, votesGivenByThisUser.length > 0);
			});
	}
}

module.exports = pollHandler;
<|endoftext|>


<commit_before>var Shell = Shell || {
    commands: {},

    // I/O functions

    rawWrite: function(s, to, style){
	s = s.replace(/\n/g, "
");
	s = "
" + s + "
";
	if (to){
	    s = "/w " + to.split(" ", 1)[0] + " " + s;
	}
	sendChat("Shell", s);
    },

    write: function(s, to, style){
	Shell.rawWrite(s.replace(/</g, "<").replace(/>/g, ">"), to, style);
    },

    writeAndLog: function(s, to){
	Shell.write(s, to);
	_.each(s.split("\n"), log);
    },

    writeErr: function(s){
	Shell.writeAndLog(s, "gm");
    },

    // command registration

    registerCommand: function(cmd, sig, desc, fn){
	// error checking
	if (!cmd){
	    var errMsg = "Error: Cannot register empty command";
	    if (sig){
		errMsg += " (signature: " + sig + ")";
	    }
	    Shell.writeErr(errMsg);
	    return;
	}
	if (!fn){
	    Shell.writeErr("Error: Cannot register command \"" + cmd + "\" without a callback");
	    return;
	}

	// fix up the arguments if necessary
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}
	if (!sig){
	    sig = cmd;
	}

	// check for already-registered command of the same name
	if (Shell.commands[cmd]){
	    if ((Shell.commands[cmd].signature != sig) || (Shell.commands[cmd].description != desc) || (Shell.commands[cmd].callback != fn)){
		Shell.writeErr("Error: Command with name \"" + cmd + "\" already registered");
	    }
	    return;
	}

	// register command
	Shell.commands[cmd] = {
	    signature:		sig,
	    description:	desc,
	    callback:		fn
	};
    },

    unregisterCommand: function(cmd){
	// error checking
	if (!cmd){
	    Shell.writeErr("Error: Cannot unregister empty command");
	    return;
	}

	// fix up argument if necessary
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}

	// verify command exists
	if (!Shell.commands[cmd]){
	    Shell.writeErr("Error: Command \"" + cmd + "\" not registered");
	    return;
	}

	// unregister command
	delete Shell.commands[cmd];
	if (state.Shell.userPermissions[cmd]){
	    delete state.Shell.userPermissions[cmd];
	}
    },

    // utility functions

    tokenize: function(s){
	var retval = [];
	var curTok = "";
	var quote = false;
	while (s.length > 0){
	    if (quote){
		// in quoted string; look for terminating quote
		var idx = s.indexOf(quote);
		if (idx < 0){
		    return "Error: Unmatched " + quote;
		}
		curTok += s.substr(0, idx);
		s = s.substr(idx + 1);
		quote = "";
		continue;
	    }
	    var idx = s.search(/[\s'"]/);
	    if (idx < 0){
		// no more quotes or whitespace, just add the rest of the string to the current token and terminate
		curTok += s;
		if (curTok){
		    retval.push(curTok);
		}
		break;
	    }
	    curTok += s.substr(0, idx);
	    var c = s.charAt(idx);
	    s = s.substr(idx + 1);
	    if ((c == "'") || (c == '"')){
		// got a quote; start quoted string
		quote = c;
	    }
	    else{
		// got whitespace; push current token and start looking for a new token
		if (curTok){
		    retval.push(curTok);
		}
		curTok = "";
	    }
	}
	return retval;
    },

    // built-in commands

    helpCommand: function(args, msg){
	var commandKeys = [];
	for (var cmd in Shell.commands){
	    if (Shell.hasPermission(msg, cmd)){
		commandKeys.push(cmd);
	    }
	}
	commandKeys.sort();
	var helpMsg = "";
	for (var i = 0; i < commandKeys.length; i++){
	    helpMsg += (i > 0 ? "\n" : "") + Shell.commands[commandKeys[i]].signature;
	    if (Shell.commands[commandKeys[i]].description){
		helpMsg += "\n\t" + Shell.commands[commandKeys[i]].description;
	    }
	}
	if (helpMsg){
	    Shell.write("Shell Commands:", msg.who);
	    Shell.write(helpMsg, msg.who, "font-size: x-small");
	}
    },

    permissionCommand: function(args, msg){
	function showHelp(){
	    Shell.write(args[0] + " add <command> [player]", msg.who);
	    Shell.write("\tAdd permission for specified player to execute specified command.", msg.who);
	    Shell.write("\tIf no player is specified, adds world-execute permission.", msg.who);
	    Shell.write(args[0] + " remove <command> [player]", msg.who);
	    Shell.write("\tRemove permission for specified player to execute specified command.", msg.who);
	    Shell.write("\tIf no player is specified, removes world-execute permission.", msg.who);
	}

	if ((args.length > 1) && ((args[1] == "-h") || (args[1] == "--help") || (args[1] == "help"))){
	    showHelp();
	    return;
	}
	if (args.length < 3){
	    Shell.write(args[0] + " requires at least two arguments: add|remove and a command", msg.who);
	    showHelp();
	    return;
	}
	if (!args[2]){
	    Shell.write("Unrecognized command: \"\"", msg.who);
	    showHelp();
	    return;
	}
	var cmd = args[2];
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}
	if (!Shell.commands[cmd]){
	    Shell.write("Unrecognized command: " + cmd, msg.who);
	    return;
	}

	var playerId = (args.length > 3 ? args[3] : "");
	if (playerId){
	    var players = _.union(findObjs({_type: "player", _displayname: playerId}), findObjs({_type: "player", _d20userid: playerId}));
	    if (players.length < 1){
		Shell.write("Unable to find user matching " + playerId, msg.who);
		players = findObjs({_type: "player"});
	    }
	    if (players.length > 1){
		Shell.write("Found more than one user matching " + playerId, msg.who);
	    }
	    if (players.length != 1){
		Shell.write("Please try again using one of: " + (_.map(players, function(p){ return p.get('_d20userid'); })).join(", "), msg.who);
		return;
	    }
	    playerId = players[0].id;
	}

	switch (args[1]){
	case "add":
	    // add userId to state.Shell.userPermissions[cmd] (if not already present), making sure to keep the list sorted
	    if (!state.Shell.userPermissions[cmd]){
		state.Shell.userPermissions[cmd] = [];
	    }
	    if (_.contains(state.Shell.userPermissions[cmd], playerId)){ return; }
	    state.Shell.userPermissions[cmd].splice(_.sortedIndex(state.Shell.userPermissions[cmd], playerId), 0, playerId);
	    break;
	case "remove":
	    // remove playerId from state.Shell.userPermissions[cmd] (if present)
	    if (!state.Shell.userPermissions[cmd]){ return; }
	    var idx = state.Shell.userPermissions[cmd].indexOf(playerId);
	    if (idx < 0){ return; }
	    state.Shell.userPermissions[cmd].splice(idx, 1);
	    break;
	default:
	    Shell.write("Unrecognized operation: " + args[1], msg.who);
	    showHelp();
	    return;
	}
    },

    // internal functions

    isFromGM: function(msg){
	// try to determine if message sender is GM from msg
	var player = getObj("player", msg.playerid);
	if ((player.get('speakingas') == "") || (player.get('speakingas') == "player|" + msg.playerid)){
	    return msg.who != player.get('_displayname');
	}

	// couldn't figure it out from msg; try to use isGM if it exists
	// we'd try this first if there were a way to tell the difference between "player not GM" and "player GM status unknown"
	if ((typeof(isGM) != "undefined") && (isGM) && (_.isFunction(isGM))){
	    return isGM(msg.playerid);
	}
    },

    hasPermission: function(msg, cmd){
	if (Shell.isFromGM(msg)){ return true; }
	if (state.Shell.userPermissions[cmd]){
	    if (_.contains(state.Shell.userPermissions[cmd], msg.playerid, true)){ return true; }
	    if (_.contains(state.Shell.userPermissions[cmd], "", true)){ return true; }
	}
/////
//
	//maybe add handling for groups
//
/////
	return false;
    },

    handleChatMessage: function(msg){
	if (msg.type != "api"){ return; }

	// tokenize command string
	var tokens = Shell.tokenize(msg.content);
	if (typeof(tokens) == typeof("")){
	    Shell.writeAndLog(tokens, msg.who);
	    return;
	}
	if (tokens.length <= 0){ return; }

	if (!Shell.commands[tokens[0]]){
	    // ignore unregistered command
	    return;
	}

	if (!Shell.hasPermission(msg, tokens[0])){
	    Shell.write("Error: You do not have permission to execute command " + tokens[0]);
	    return;
	}

	// execute command callback
	Shell.commands[tokens[0]].callback(tokens, _.clone(msg));
    },

    init: function(){
	// initialize stored state
	state.Shell = state.Shell || {};
	state.Shell.userPermissions = state.Shell.userPermissions || {};

	// register built-in commands
	Shell.registerCommand("!help", "!help", "Show this help message", Shell.helpCommand);
	state.Shell.userPermissions["!help"] = [""];
	Shell.registerCommand("!shell-permission", "!shell-permission add|remove <command> [player]",
			    "Add or remove permission for specified command", Shell.permissionCommand);

	// register chat event handler
	on("chat:message", Shell.handleChatMessage);
    }
};

on("ready", Shell.init);
<commit_msg>Add "from" argument to write/rawWrite, so users can send from source other than "Shell"<commit_after>var Shell = Shell || {
    commands: {},

    // I/O functions

    rawWrite: function(s, to, style, from){
	s = s.replace(/\n/g, "
");
	s = "
" + s + "
";
	if (to){
	    s = "/w " + to.split(" ", 1)[0] + " " + s;
	}
	sendChat((typeof(from) == typeof("") ? from : "Shell"), s);
    },

    write: function(s, to, style, from){
	Shell.rawWrite(s.replace(/</g, "<").replace(/>/g, ">"), to, style, from);
    },

    writeAndLog: function(s, to){
	Shell.write(s, to);
	_.each(s.split("\n"), log);
    },

    writeErr: function(s){
	Shell.writeAndLog(s, "gm");
    },

    // command registration

    registerCommand: function(cmd, sig, desc, fn){
	// error checking
	if (!cmd){
	    var errMsg = "Error: Cannot register empty command";
	    if (sig){
		errMsg += " (signature: " + sig + ")";
	    }
	    Shell.writeErr(errMsg);
	    return;
	}
	if (!fn){
	    Shell.writeErr("Error: Cannot register command \"" + cmd + "\" without a callback");
	    return;
	}

	// fix up the arguments if necessary
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}
	if (!sig){
	    sig = cmd;
	}

	// check for already-registered command of the same name
	if (Shell.commands[cmd]){
	    if ((Shell.commands[cmd].signature != sig) || (Shell.commands[cmd].description != desc) || (Shell.commands[cmd].callback != fn)){
		Shell.writeErr("Error: Command with name \"" + cmd + "\" already registered");
	    }
	    return;
	}

	// register command
	Shell.commands[cmd] = {
	    signature:		sig,
	    description:	desc,
	    callback:		fn
	};
    },

    unregisterCommand: function(cmd){
	// error checking
	if (!cmd){
	    Shell.writeErr("Error: Cannot unregister empty command");
	    return;
	}

	// fix up argument if necessary
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}

	// verify command exists
	if (!Shell.commands[cmd]){
	    Shell.writeErr("Error: Command \"" + cmd + "\" not registered");
	    return;
	}

	// unregister command
	delete Shell.commands[cmd];
	if (state.Shell.userPermissions[cmd]){
	    delete state.Shell.userPermissions[cmd];
	}
    },

    // utility functions

    tokenize: function(s){
	var retval = [];
	var curTok = "";
	var quote = false;
	while (s.length > 0){
	    if (quote){
		// in quoted string; look for terminating quote
		var idx = s.indexOf(quote);
		if (idx < 0){
		    return "Error: Unmatched " + quote;
		}
		curTok += s.substr(0, idx);
		s = s.substr(idx + 1);
		quote = "";
		continue;
	    }
	    var idx = s.search(/[\s'"]/);
	    if (idx < 0){
		// no more quotes or whitespace, just add the rest of the string to the current token and terminate
		curTok += s;
		if (curTok){
		    retval.push(curTok);
		}
		break;
	    }
	    curTok += s.substr(0, idx);
	    var c = s.charAt(idx);
	    s = s.substr(idx + 1);
	    if ((c == "'") || (c == '"')){
		// got a quote; start quoted string
		quote = c;
	    }
	    else{
		// got whitespace; push current token and start looking for a new token
		if (curTok){
		    retval.push(curTok);
		}
		curTok = "";
	    }
	}
	return retval;
    },

    // built-in commands

    helpCommand: function(args, msg){
	var commandKeys = [];
	for (var cmd in Shell.commands){
	    if (Shell.hasPermission(msg, cmd)){
		commandKeys.push(cmd);
	    }
	}
	commandKeys.sort();
	var helpMsg = "";
	for (var i = 0; i < commandKeys.length; i++){
	    helpMsg += (i > 0 ? "\n" : "") + Shell.commands[commandKeys[i]].signature;
	    if (Shell.commands[commandKeys[i]].description){
		helpMsg += "\n\t" + Shell.commands[commandKeys[i]].description;
	    }
	}
	if (helpMsg){
	    Shell.write("Shell Commands:", msg.who);
	    Shell.write(helpMsg, msg.who, "font-size: x-small");
	}
    },

    permissionCommand: function(args, msg){
	function showHelp(){
	    Shell.write(args[0] + " add <command> [player]", msg.who);
	    Shell.write("\tAdd permission for specified player to execute specified command.", msg.who);
	    Shell.write("\tIf no player is specified, adds world-execute permission.", msg.who);
	    Shell.write(args[0] + " remove <command> [player]", msg.who);
	    Shell.write("\tRemove permission for specified player to execute specified command.", msg.who);
	    Shell.write("\tIf no player is specified, removes world-execute permission.", msg.who);
	}

	if ((args.length > 1) && ((args[1] == "-h") || (args[1] == "--help") || (args[1] == "help"))){
	    showHelp();
	    return;
	}
	if (args.length < 3){
	    Shell.write(args[0] + " requires at least two arguments: add|remove and a command", msg.who);
	    showHelp();
	    return;
	}
	if (!args[2]){
	    Shell.write("Unrecognized command: \"\"", msg.who);
	    showHelp();
	    return;
	}
	var cmd = args[2];
	if (cmd.charAt(0) != '!'){
	    cmd = "!" + cmd;
	}
	if (!Shell.commands[cmd]){
	    Shell.write("Unrecognized command: " + cmd, msg.who);
	    return;
	}

	var playerId = (args.length > 3 ? args[3] : "");
	if (playerId){
	    var players = _.union(findObjs({_type: "player", _displayname: playerId}), findObjs({_type: "player", _d20userid: playerId}));
	    if (players.length < 1){
		Shell.write("Unable to find user matching " + playerId, msg.who);
		players = findObjs({_type: "player"});
	    }
	    if (players.length > 1){
		Shell.write("Found more than one user matching " + playerId, msg.who);
	    }
	    if (players.length != 1){
		Shell.write("Please try again using one of: " + (_.map(players, function(p){ return p.get('_d20userid'); })).join(", "), msg.who);
		return;
	    }
	    playerId = players[0].id;
	}

	switch (args[1]){
	case "add":
	    // add userId to state.Shell.userPermissions[cmd] (if not already present), making sure to keep the list sorted
	    if (!state.Shell.userPermissions[cmd]){
		state.Shell.userPermissions[cmd] = [];
	    }
	    if (_.contains(state.Shell.userPermissions[cmd], playerId)){ return; }
	    state.Shell.userPermissions[cmd].splice(_.sortedIndex(state.Shell.userPermissions[cmd], playerId), 0, playerId);
	    break;
	case "remove":
	    // remove playerId from state.Shell.userPermissions[cmd] (if present)
	    if (!state.Shell.userPermissions[cmd]){ return; }
	    var idx = state.Shell.userPermissions[cmd].indexOf(playerId);
	    if (idx < 0){ return; }
	    state.Shell.userPermissions[cmd].splice(idx, 1);
	    break;
	default:
	    Shell.write("Unrecognized operation: " + args[1], msg.who);
	    showHelp();
	    return;
	}
    },

    // internal functions

    isFromGM: function(msg){
	// try to determine if message sender is GM from msg
	var player = getObj("player", msg.playerid);
	if ((player.get('speakingas') == "") || (player.get('speakingas') == "player|" + msg.playerid)){
	    return msg.who != player.get('_displayname');
	}

	// couldn't figure it out from msg; try to use isGM if it exists
	// we'd try this first if there were a way to tell the difference between "player not GM" and "player GM status unknown"
	if ((typeof(isGM) != "undefined") && (isGM) && (_.isFunction(isGM))){
	    return isGM(msg.playerid);
	}
    },

    hasPermission: function(msg, cmd){
	if (Shell.isFromGM(msg)){ return true; }
	if (state.Shell.userPermissions[cmd]){
	    if (_.contains(state.Shell.userPermissions[cmd], msg.playerid, true)){ return true; }
	    if (_.contains(state.Shell.userPermissions[cmd], "", true)){ return true; }
	}
/////
//
	//maybe add handling for groups
//
/////
	return false;
    },

    handleChatMessage: function(msg){
	if (msg.type != "api"){ return; }

	// tokenize command string
	var tokens = Shell.tokenize(msg.content);
	if (typeof(tokens) == typeof("")){
	    Shell.writeAndLog(tokens, msg.who);
	    return;
	}
	if (tokens.length <= 0){ return; }

	if (!Shell.commands[tokens[0]]){
	    // ignore unregistered command
	    return;
	}

	if (!Shell.hasPermission(msg, tokens[0])){
	    Shell.write("Error: You do not have permission to execute command " + tokens[0]);
	    return;
	}

	// execute command callback
	Shell.commands[tokens[0]].callback(tokens, _.clone(msg));
    },

    init: function(){
	// initialize stored state
	state.Shell = state.Shell || {};
	state.Shell.userPermissions = state.Shell.userPermissions || {};

	// register built-in commands
	Shell.registerCommand("!help", "!help", "Show this help message", Shell.helpCommand);
	state.Shell.userPermissions["!help"] = [""];
	Shell.registerCommand("!shell-permission", "!shell-permission add|remove <command> [player]",
			    "Add or remove permission for specified command", Shell.permissionCommand);

	// register chat event handler
	on("chat:message", Shell.handleChatMessage);
    }
};

on("ready", Shell.init);
<|endoftext|>


<commit_before>class ProductController {
    constructor(data) {
        this.data = data;
    }

    loadProductForm(req, res) {
        const shopId = req.params.id;

        this.data.shops.findById(shopId)
            .then((shop) => {
                res.status(200)
                    .render('product/addNewProduct', {
                        shop: shop
                    });
            });
    }

    createProduct(req, res) {
        const shopId = req.params.id;
        const productData = req.body;
        productData.shopId = shopId;

        return this.data.products.create(productData)
            .then((product) => {
                this.data.shops.assignProductToShop(shopId, product)
                    .then(() => {
                        req.flash('success', 'Product successfully added!');
                        res.redirect('/shop/' + shopId);
                    });
            })
            .catch((err) => {
                req.flash('error', err);
                res.redirect('/shop/' + shopId + '/add-product');
            });
    }

    loadProductInfo(req, res) {
        const productId = req.params.productId;

        this.data.products.findById(productId)
            .then((product) => {
                return res.send({
                    product: product
                });
            });
    }

    updateProduct(req, res) {
        const productEditData = req.body;
        const productId = req.params.productId;
        const shopId = req.params.id;

        return Promise.all([
            this.data.products.updateProductById(productId, productEditData),
            this.data.shops.updateProductInShop(
                shopId,
                productId,
                productEditData)
        ])
            .then(() => {
                req.flash(
                    'success',
                    'Product successfully updated!');

                return res.send({ locationUrl: '/shop/' + shopId });
            })
            .catch((err) => {
                req.flash('error', err);
                return res.send({ locationUrl: '/shop/' + shopId });
            });
    }

    deleteProduct(req, res) {
        const productId = req.params.productId;
        const shopId = req.params.id;

        return Promise.all([
            this.data.products.deleteById(productId),
            this.data.shops.deleteProductFromShop(shopId, productId)
        ])
            .then(() => {
                req.flash(
                    'success',
                    'Product successfully deleted!');

                return res.send({ locationUrl: '/shop/' + shopId });
            })
            .catch((err) => {
                req.flash('error', err);
                return res.send({ locationUrl: '/shop/' + shopId });
            });
    }
}

const init = (data) => {
    return new ProductController(data);
};

module.exports = { init };<commit_msg>Authorization checks added to product-controller.<commit_after>class ProductController {
    constructor(data) {
        this.data = data;
    }

    loadProductForm(req, res) {
        if (!req.isAuthenticated()) {
            return res.redirect('/auth/sign-in');
        }

        if (!req.user.isProUser) {
            return res.render('unauthorized');
        }

        const shopId = req.params.id;

        return this.data.shops.findById(shopId)
            .then((shop) => {
                res.status(200)
                    .render('product/addNewProduct', {
                        shop: shop
                    });
            });
    }

    createProduct(req, res) {
        if (!req.isAuthenticated()) {
            return res.redirect('/auth/sign-in');
        }

        if (!req.user.isProUser) {
            return res.render('unauthorized');
        }

        const shopId = req.params.id;
        const productData = req.body;
        productData.shopId = shopId;

        return this.data.products.create(productData)
            .then((product) => {
                this.data.shops.assignProductToShop(shopId, product)
                    .then(() => {
                        req.flash('success', 'Product successfully added!');
                        res.redirect('/shop/' + shopId);
                    });
            })
            .catch((err) => {
                req.flash('error', err);
                res.redirect('/shop/' + shopId + '/add-product');
            });
    }

    loadProductInfo(req, res) {
        const productId = req.params.productId;

        return this.data.products.findById(productId)
            .then((product) => {
                return res.send({
                    product: product
                });
            });
    }

    updateProduct(req, res) {
        if (!req.isAuthenticated()) {
            return res.redirect('/auth/sign-in');
        }

        if (!req.user.isProUser) {
            return res.render('unauthorized');
        }

        const productEditData = req.body;
        const productId = req.params.productId;
        const shopId = req.params.id;

        return Promise.all([
            this.data.products.updateProductById(productId, productEditData),
            this.data.shops.updateProductInShop(
                shopId,
                productId,
                productEditData)
        ])
            .then(() => {
                req.flash(
                    'success',
                    'Product successfully updated!');

                return res.send({
                    locationUrl: '/shop/' + shopId
                });
            })
            .catch((err) => {
                req.flash('error', err);
                return res.send({
                    locationUrl: '/shop/' + shopId
                });
            });
    }

    deleteProduct(req, res) {
        if (!req.isAuthenticated()) {
            return res.redirect('/auth/sign-in');
        }

        if (!req.user.isProUser) {
            return res.render('unauthorized');
        }

        const productId = req.params.productId;
        const shopId = req.params.id;

        return Promise.all([
            this.data.products.deleteById(productId),
            this.data.shops.deleteProductFromShop(shopId, productId)
        ])
            .then(() => {
                req.flash(
                    'success',
                    'Product successfully deleted!');

                return res.send({
                    locationUrl: '/shop/' + shopId
                });
            })
            .catch((err) => {
                req.flash('error', err);
                return res.send({
                    locationUrl: '/shop/' + shopId
                });
            });
    }
}

const init = (data) => {
    return new ProductController(data);
};

module.exports = { init };<|endoftext|>