<commit_before>// Copyright © 2011 Aapo Laitinen <aapo.laitinen@iki.fi> unless otherwise noted

define(['engine/util/mathlib', 'engine/client/UIRenderer', 'engine/util/Event'], function (mathlib, UIRenderer, Event) {

	function Client(game, canvas) {
		var self = this;
		assert(game && typeof game === 'object', 'Client: game must be an object');
		assert(canvas, 'Client: canvas is required');
		this.game = game;
		this.canvas = canvas;
		this.gl = null;
		this.widgets = [];
		this.mouseOverWidget = null;
		this.uiRenderer = new UIRenderer();
		this.onresizewindow = null;
		this.onDraw = new Event();
		//
		// User interface state
		//
		this.selectedActors = [];
		//
		// Pacing information
		//
		// Interpolation factor. Value 0 means that the frame that is being rendered
		// or that has been rendered reflects the current simulation state. Value -1
		// means that the frame that is being rendered or has been rendered reflects
		// the previous simulation state.
		this.factor = 0;
		this.lastDrawn = 0;
		this.msecsSinceDrawn = 0;

		// Acquire drawing context

		var glOptions = {
		};

		try {
			this.gl = this.canvas.getContext('webgl', glOptions);
			if (!this.gl) {
				this.gl = this.canvas.getContext('experimental-webgl', glOptions);
			}
		} catch (e) {
			// TODO: Better error message
			alert('Got exception ' + e + ' when attempting to initialize WebGL context.');
			return;
		}
		if (!this.gl) {
			// TODO: Better error message
			alert('Could not initialize WebGL context. Try a better browser?');
			return;
		}

		// requestAnimationFrame is still under development, so try various
		// vendor-prefixed versions.
		var requestAnimationFrame =
				window.requestAnimationFrame ||
				window.mozRequestAnimationFrame ||
				window.webkitRequestAnimationFrame ||
				function (callback, elm) {
					setTimeout(callback, 10);
				};

		// If contexts are available, set up event handlers

		window.setInterval(function () {
			self.game.gameLoop();
		}, 10);

		requestAnimationFrame.call(window, function handleAnimationFrame() {
			requestAnimationFrame.call(window, handleAnimationFrame, canvas);
			self.drawLoop();
		}, canvas);

		this.canvas.addEventListener('click', function (evt) {
			self.handleClick(evt);
		}, false);

		this.canvas.addEventListener('mousemove', function (evt) {
			self.handleMouseMove(evt);
		}, false);

		this.canvas.addEventListener('mouseout', function (evt) {
			self.handleMouseOut(evt);
		}, false);

		document.addEventListener('keypress', function (evt) {
			self.handleKeyPress(evt);
		}, false);

		window.addEventListener('resize', function (evt) {
			var func = self.onresizewindow;
			if (func) {
				func.call(self, evt);
			}
		}, false);

		// WebGL context initialization
		// FIXME: Must be done again if the context is lost and restored

		var gl = this.gl;
		gl.clearColor(0.0, 0.0, 0.0, 0.0);
		gl.clearDepth(1.0);
	}

	// Set the currently selected actors to certain array
	Client.prototype.setSelection = function (arr) {
		this.selectedActors = arr;
	};

	Client.prototype.add = function (widget) {
		assert(
			widget.handleClick && widget.handleMouseMove && widget.handleKeyPress,
			'Client.add: widget must handle clicks, mouse moves and key presses'
		);
		this.widgets.push(widget);
	};

	Client.prototype.remove = function (widget) {
		var index = this.widgets.indexOf(widget);
		if (index >= 0) {
			this.widgets.splice(index, 1);
		}
	};

	Client.prototype.normalizedOffset = function (evt) {
		var bounds = this.canvas.getBoundingClientRect();
		return new mathlib.Vec(
			evt.clientX - bounds.left,
			evt.clientY - bounds.top
		);
	};

	// Drawing loop. This should be called repeatedly, preferably using
	// requestAnimationFrame to remove unnecessary updates.
	Client.prototype.drawLoop = function () {
		var timeNow = (new Date()).getTime();
		if (this.game.reallyRunning) {
			this.factor = 1 - (timeNow - this.game.lastTickAt) / this.game.msecsPerTick;
			if (this.factor < 0) {
				this.factor = 0;
			}
		} else {
			this.factor = 0;
		}
		if (this.lastDrawn) {
			var sinceDrawn = timeNow - this.lastDrawn;
			if (this.game.cappedToFps > 0 && sinceDrawn < 1000 / this.game.cappedToFps) {
				return;
			}
			this.msecsSinceDrawn = sinceDrawn;
		} else {
			this.msecsSinceDrawn = 0;
		}
		this.lastDrawn = timeNow;

		// Do the actual drawing

		var gl = this.gl;
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
		for (var i = 0; i < this.widgets.length; ++i) {
			this.widgets[i].draw(gl);
		}
		this.uiRenderer.draw(gl);
		this.onDraw.emit();
	};

	Client.prototype.handleClick = function (evt) {
		evt.preventDefault();
		var offset = this.normalizedOffset(evt);
		for (var i = this.widgets.length - 1; i >= 0; --i) {
			var widget = this.widgets[i];
			if (offset.x >= widget.x
					&& offset.x < widget.x + widget.width
					&& offset.y >= widget.y
					&& offset.y < widget.y + widget.height) {
				if (widget.handleClick(offset.x - widget.x, offset.y - widget.y) !== false) {
					return;
				}
			}
		}
	};

	Client.prototype.handleMouseMove = function (evt) {
		evt.preventDefault();
		var offset = this.normalizedOffset(evt);
		if (this.mouseOverWidget) {
			var widget = this.mouseOverWidget;
			if (offset.x < widget.x
					|| offset.x >= widget.x + widget.width
					|| offset.y < widget.y
					|| offset.y >= widget.y + widget.height) {
				widget.handleMouseOut();
				this.mouseOverWidget = null;
			}
		}
		for (var i = this.widgets.length - 1; i >= 0; --i) {
			var widget = this.widgets[i];
			if (offset.x >= widget.x
					&& offset.x < widget.x + widget.width
					&& offset.y >= widget.y
					&& offset.y < widget.y + widget.height) {
				if (widget.handleMouseMove(offset.x - widget.x, offset.y - widget.y) !== false) {
					this.mouseOverWidget = widget;
					return;
				}
			}
		}
	};

	Client.prototype.handleMouseOut = function (evt) {
		evt.preventDefault();
		if (this.mouseOverWidget) {
			this.mouseOverWidget.handleMouseOut();
			this.mouseOverWidget = null;
		}
	};

	Client.prototype.handleKeyPress = function (evt) {
		evt.preventDefault();
		var code = evt.keyCode || evt.charCode;
		if (code >= 65 && code <= 90) {
			var letter = String.fromCharCode(code + 32);
		} else if (code >= 97 && code <= 122) {
			var letter = String.fromCharCode(code);
		} else {
			return;
		}
		for (var i = this.widgets.length - 1; i >= 0; --i) {
			if (this.widgets[i].handleKeyPress(letter) !== false) {
				return;
			}
		}
	};

	return Client;

});<commit_msg>Enable depth buffering<commit_after>// Copyright © 2011 Aapo Laitinen <aapo.laitinen@iki.fi> unless otherwise noted

define(['engine/util/mathlib', 'engine/client/UIRenderer', 'engine/util/Event'], function (mathlib, UIRenderer, Event) {

	function Client(game, canvas) {
		var self = this;
		assert(game && typeof game === 'object', 'Client: game must be an object');
		assert(canvas, 'Client: canvas is required');
		this.game = game;
		this.canvas = canvas;
		this.gl = null;
		this.widgets = [];
		this.mouseOverWidget = null;
		this.uiRenderer = new UIRenderer();
		this.onresizewindow = null;
		this.onDraw = new Event();
		//
		// User interface state
		//
		this.selectedActors = [];
		//
		// Pacing information
		//
		// Interpolation factor. Value 0 means that the frame that is being rendered
		// or that has been rendered reflects the current simulation state. Value -1
		// means that the frame that is being rendered or has been rendered reflects
		// the previous simulation state.
		this.factor = 0;
		this.lastDrawn = 0;
		this.msecsSinceDrawn = 0;

		// Acquire drawing context

		var glOptions = {
		};

		try {
			this.gl = this.canvas.getContext('webgl', glOptions);
			if (!this.gl) {
				this.gl = this.canvas.getContext('experimental-webgl', glOptions);
			}
		} catch (e) {
			// TODO: Better error message
			alert('Got exception ' + e + ' when attempting to initialize WebGL context.');
			return;
		}
		if (!this.gl) {
			// TODO: Better error message
			alert('Could not initialize WebGL context. Try a better browser?');
			return;
		}

		// requestAnimationFrame is still under development, so try various
		// vendor-prefixed versions.
		var requestAnimationFrame =
				window.requestAnimationFrame ||
				window.mozRequestAnimationFrame ||
				window.webkitRequestAnimationFrame ||
				function (callback, elm) {
					setTimeout(callback, 10);
				};

		// If contexts are available, set up event handlers

		window.setInterval(function () {
			self.game.gameLoop();
		}, 10);

		requestAnimationFrame.call(window, function handleAnimationFrame() {
			requestAnimationFrame.call(window, handleAnimationFrame, canvas);
			self.drawLoop();
		}, canvas);

		this.canvas.addEventListener('click', function (evt) {
			self.handleClick(evt);
		}, false);

		this.canvas.addEventListener('mousemove', function (evt) {
			self.handleMouseMove(evt);
		}, false);

		this.canvas.addEventListener('mouseout', function (evt) {
			self.handleMouseOut(evt);
		}, false);

		document.addEventListener('keypress', function (evt) {
			self.handleKeyPress(evt);
		}, false);

		window.addEventListener('resize', function (evt) {
			var func = self.onresizewindow;
			if (func) {
				func.call(self, evt);
			}
		}, false);

		// WebGL context initialization
		// FIXME: Must be done again if the context is lost and restored

		var gl = this.gl;

		// Enable depth buffering
		// Defaults to depth mask enabled and depth range of 0 to 1
		gl.enable(gl.DEPTH_TEST);
		gl.depthFunc(gl.LEQUAL);

		gl.clearColor(0.0, 0.0, 0.0, 0.0);
		gl.clearDepth(1.0);
	}

	// Set the currently selected actors to certain array
	Client.prototype.setSelection = function (arr) {
		this.selectedActors = arr;
	};

	Client.prototype.add = function (widget) {
		assert(
			widget.handleClick && widget.handleMouseMove && widget.handleKeyPress,
			'Client.add: widget must handle clicks, mouse moves and key presses'
		);
		this.widgets.push(widget);
	};

	Client.prototype.remove = function (widget) {
		var index = this.widgets.indexOf(widget);
		if (index >= 0) {
			this.widgets.splice(index, 1);
		}
	};

	Client.prototype.normalizedOffset = function (evt) {
		var bounds = this.canvas.getBoundingClientRect();
		return new mathlib.Vec(
			evt.clientX - bounds.left,
			evt.clientY - bounds.top
		);
	};

	// Drawing loop. This should be called repeatedly, preferably using
	// requestAnimationFrame to remove unnecessary updates.
	Client.prototype.drawLoop = function () {
		var timeNow = (new Date()).getTime();
		if (this.game.reallyRunning) {
			this.factor = 1 - (timeNow - this.game.lastTickAt) / this.game.msecsPerTick;
			if (this.factor < 0) {
				this.factor = 0;
			}
		} else {
			this.factor = 0;
		}
		if (this.lastDrawn) {
			var sinceDrawn = timeNow - this.lastDrawn;
			if (this.game.cappedToFps > 0 && sinceDrawn < 1000 / this.game.cappedToFps) {
				return;
			}
			this.msecsSinceDrawn = sinceDrawn;
		} else {
			this.msecsSinceDrawn = 0;
		}
		this.lastDrawn = timeNow;

		// Do the actual drawing

		var gl = this.gl;
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
		for (var i = 0; i < this.widgets.length; ++i) {
			this.widgets[i].draw(gl);
		}
		this.uiRenderer.draw(gl);
		this.onDraw.emit();
	};

	Client.prototype.handleClick = function (evt) {
		evt.preventDefault();
		var offset = this.normalizedOffset(evt);
		for (var i = this.widgets.length - 1; i >= 0; --i) {
			var widget = this.widgets[i];
			if (offset.x >= widget.x
					&& offset.x < widget.x + widget.width
					&& offset.y >= widget.y
					&& offset.y < widget.y + widget.height) {
				if (widget.handleClick(offset.x - widget.x, offset.y - widget.y) !== false) {
					return;
				}
			}
		}
	};

	Client.prototype.handleMouseMove = function (evt) {
		evt.preventDefault();
		var offset = this.normalizedOffset(evt);
		if (this.mouseOverWidget) {
			var widget = this.mouseOverWidget;
			if (offset.x < widget.x
					|| offset.x >= widget.x + widget.width
					|| offset.y < widget.y
					|| offset.y >= widget.y + widget.height) {
				widget.handleMouseOut();
				this.mouseOverWidget = null;
			}
		}
		for (var i = this.widgets.length - 1; i >= 0; --i) {
			var widget = this.widgets[i];
			if (offset.x >= widget.x
					&& offset.x < widget.x + widget.width
					&& offset.y >= widget.y
					&& offset.y < widget.y + widget.height) {
				if (widget.handleMouseMove(offset.x - widget.x, offset.y - widget.y) !== false) {
					this.mouseOverWidget = widget;
					return;
				}
			}
		}
	};

	Client.prototype.handleMouseOut = function (evt) {
		evt.preventDefault();
		if (this.mouseOverWidget) {
			this.mouseOverWidget.handleMouseOut();
			this.mouseOverWidget = null;
		}
	};

	Client.prototype.handleKeyPress = function (evt) {
		evt.preventDefault();
		var code = evt.keyCode || evt.charCode;
		if (code >= 65 && code <= 90) {
			var letter = String.fromCharCode(code + 32);
		} else if (code >= 97 && code <= 122) {
			var letter = String.fromCharCode(code);
		} else {
			return;
		}
		for (var i = this.widgets.length - 1; i >= 0; --i) {
			if (this.widgets[i].handleKeyPress(letter) !== false) {
				return;
			}
		}
	};

	return Client;

});<|endoftext|>


<commit_before>// @flow

import React from 'react'
import cx from 'classnames'
import listify from 'listify'
import sample from 'lodash/sample'
import {Set} from 'immutable'
import {connect} from 'react-redux'
import {Card} from '../../components/card'
import {AvatarLetter} from '../../components/avatar-letter'
import {ContentEditable} from '../../components/content-editable'
import {AutoSizedInput} from '../../components/autosize'
import {
	changeStudent,
	type ChangeStudentFunc,
} from '../../redux/students/actions/change'
import {Student, type AreaQuery} from '@gob/object-student'
import {checkStudentAgainstArea} from '../../workers/check-student'
import {loadArea} from '../../helpers/load-area'
import uniqueId from 'lodash/uniqueId'

import './student-summary.scss'

const welcomeMessages = [
	'Hi, ',
	'Hi there, ',
	'Hello, ',
	'こんにちは、', // japanese
	'ようこそ、', // japanese
	'Fram! Fram! ',
	'Salut, ',
	'Aloha, ', // hawaiian
	'Привет, ',
	'Вітаю, ',
	'Sawubona, ',
	'Hei, ',
	'Hola, ', // spanish
	'Bonjour, ', // french
	'Hallo, ', // german
	'nyob zoo ', // hmong
	'你好，', // mandarin
	'안녕하세요 ', // korean
	'สวัสดี ', // thai
	'halo, ', // indonesian
	'Salve, ', // latin
	'Χαῖρε! ', // ancient greek
]

const welcomeMessage = welcomeMessages[2]

type Props = {
	randomizeHello?: boolean,
	showAvatar?: boolean,
	showMessage?: boolean,
	student: Student,
}

type State = {
	message: string,
	canGraduate: boolean,
	creditsNeeded: ?number,
	creditsTaken: ?number,
	checking: boolean,
}

class StudentSummary extends React.Component<Props, State> {
	state = {
		message: this.props.randomizeHello
			? sample(welcomeMessages)
			: welcomeMessage,
		checking: true,
		canGraduate: false,
		creditsNeeded: null,
		creditsTaken: null,
	}

	componentDidMount() {
		this.checkGraduatability(this.props)
	}

	componentDidUpdate(prevProps: Props) {
		if (prevProps.student !== this.props.student) {
			this.checkGraduatability(this.props)
		}
	}

	checkGraduatability = async (props: Props) => {
		let {student} = props

		this.setState(() => ({checking: true}))

		let areas = student.studies.map(loadArea)
		let loadedAreas = (await Promise.all(areas))
			.filter(({error}) => !error)
			.map(({data}) => data)

		let promises = loadedAreas.map(a => checkStudentAgainstArea(student, a))
		let results = await Promise.all(promises)

		console.log(results)
		let canGraduate = results.every(r => r.computed === true)
		let {creditsNeeded = 0, creditsTaken = 0} = {}

		this.setState(() => ({
			checking: false,
			canGraduate,
			creditsNeeded,
			creditsTaken,
		}))
	}

	render() {
		let {student, showMessage = true, showAvatar = true} = this.props
		let {checking, canGraduate, creditsNeeded, creditsTaken} = this.state
		let {studies} = student
		let gradClassName = canGraduate ? 'can-graduate' : 'cannot-graduate'
		let message = this.state.message

		return (
			<Card
				as="article"
				className={cx('student-summary', gradClassName, {checking})}
			>
				<ConnectedEditor student={student} />

				{showAvatar && (
					<AvatarLetter
						className={cx(
							'student-letter',
							canGraduate ? 'can-graduate' : 'cannot-graduate',
						)}
						value={student.name}
					/>
				)}

				<DateSummary
					matriculation={student.matriculation}
					graduation={student.graduation}
				/>

				<DegreeSummary studies={studies} />

				<CreditSummary
					currentCredits={creditsTaken}
					neededCredits={creditsNeeded}
				/>

				{showMessage ?  : null}
			</Card>
		)
	}
}

export {StudentSummary}

type EditorProps = {
	student: Student,
	changeStudent: ChangeStudentFunc,
}

type EditorState = {
	name: string,
	matriculation: string,
	graduation: string,
}

class Editor extends React.Component<EditorProps, EditorState> {
	state = {
		name: this.props.student.name,
		matriculation: String(this.props.student.matriculation),
		graduation: String(this.props.student.graduation),
	}

	nameLabelId = `student-editor--${uniqueId()}`
	matriculationLabelId = `student-editor--${uniqueId()}`
	graduationLabelId = `student-editor--${uniqueId()}`

	changeName = (event: SyntheticInputEvent<HTMLInputElement>) => {
		let val = event.currentTarget.value
		this.setState(() => ({name: val}))
	}

	changeGraduation = (event: SyntheticInputEvent<HTMLInputElement>) => {
		let val = event.currentTarget.value
		this.setState(() => ({graduation: val}))
	}

	changeMatriculation = (event: SyntheticInputEvent<HTMLInputElement>) => {
		let val = event.currentTarget.value
		this.setState(() => ({matriculation: val}))
	}

	onSubmit = (event: SyntheticInputEvent<HTMLFormElement>) => {
		event.preventDefault()

		let {name, matriculation, graduation} = this.state
		let s = this.props.student

		if (matriculation !== s.matriculation) {
			s = s.setMatriculation(matriculation)
		}

		if (graduation !== s.graduation) {
			s = s.setGraduation(graduation)
		}

		if (name !== s.name) {
			s = s.setName(name)
		}

		if (s !== this.props.student) {
			this.props.changeStudent(s)
		}
	}

	render() {
		return (
			<form onSubmit={this.onSubmit} className="student-summary--editor">
				Name:
				<input
					id={this.nameLabelId}
					onChange={this.changeName}
					onBlur={this.onSubmit}
					value={this.state.name}
				/>

					Matriculation:

				<input
					id={this.matriculationLabelId}
					onChange={this.changeMatriculation}
					onBlur={this.onSubmit}
					value={this.state.matriculation}
				/>

				Graduation:
				<input
					id={this.graduationLabelId}
					onChange={this.changeGraduation}
					onBlur={this.onSubmit}
					value={this.state.graduation}
				/>
			</form>
		)
	}
}

const ConnectedEditor = connect(
	undefined,
	{changeStudent},
)(Editor)

type HeaderProps = {
	canGraduate: boolean,
	helloMessage: string,
	name: string,
	onChangeName?: string => any,
	showAvatar: boolean,
}

export class Header extends React.Component<HeaderProps> {
	handleNameChange = (val: string) => {
		console.log(val)
		this.props.onChangeName && this.props.onChangeName(val)
	}

	render() {
		const props = this.props

		return (

				{props.helloMessage}
				{String(this.props.name)}!

		)
	}
}

type FooterProps = {
	canGraduate: boolean,
}

const goodGraduationMessage =
	"It looks like you'll make it! Just follow the plan, and go over my output with your advisor a few times."
const badGraduationMessage =
	"You haven't planned everything out yet. Ask your advisor if you need help fitting everything in."

export class Footer extends React.Component<FooterProps> {
	render() {
		const msg = this.props.canGraduate
			? goodGraduationMessage
			: badGraduationMessage

		return
{msg}

	}
}

type DateSummaryProps = {
	matriculation: number,
	graduation: number,
}

export class DateSummary extends React.Component<DateSummaryProps> {
	render() {
		const props = this.props

		return (

				After matriculating in {String(props.matriculation)}, you are
				planning to graduate in {String(props.graduation)}.

		)
	}
}

type DegreeSummaryProps = {
	studies: Set<AreaQuery>,
}

export class DegreeSummary extends React.Component<DegreeSummaryProps> {
	render() {
		const grouped: {
			[key: string]: Set<{type: string, name: string, revision: string}>,
		} = this.props.studies.groupBy(s => s.type).toJSON()

		const {
			degree: dS = Set(),
			major: mS = Set(),
			concentration: cS = Set(),
			emphasis: eS = Set(),
		} = grouped

		const dCount = dS.size
		const mCount = mS.size
		const cCount = cS.size
		const eCount = eS.size

		const dWord = dCount === 1 ? 'degree' : 'degrees'
		const mWord = mCount === 1 ? 'major' : 'majors'
		const cWord = cCount === 1 ? 'concentration' : 'concentrations'
		const eWord = eCount === 1 ? 'emphasis' : 'emphases'

		const dEmph = dCount === 1 ? 'a ' : ''
		const mEmph = mCount === 1 ? 'a ' : ''
		const cEmph = cCount === 1 ? 'a ' : ''
		const eEmph = eCount === 1 ? 'an ' : ''

		const dList = listify([...dS.map(d => d.name)])
		const mList = listify([...mS.map(m => m.name)])
		const cList = listify([...cS.map(c => c.name)])
		const eList = listify([...eS.map(e => e.name)])

		return (

				You are planning on{' '}
				{dCount > 0 ? `${dEmph}${dList} ${dWord}` : `no ${dWord}`}
				{mCount || cCount || eCount
					? mCount && (cCount || eCount)
						? ', '
						: ' and '
					: ''}
				{mCount ? `${mEmph}${mWord} in ${mList}` : ''}
				{mCount && cCount ? ', and ' : ''}
				{cCount ? `${cEmph}${cWord} in ${cList}` : ''}
				{(mCount || cCount) && eCount ? ', ' : ''}
				{eCount ? `not to mention ${eEmph}${eWord} in ${eList}` : ''}
				{'.'}

		)
	}
}

type CreditSummaryProps = {
	currentCredits: ?number,
	neededCredits: ?number,
}

export class CreditSummary extends React.Component<CreditSummaryProps> {
	render() {
		let {currentCredits, neededCredits} = this.props

		if (currentCredits == null) {
			return null
		}

		if (neededCredits == null) {
			return (

					You have currently planned for {currentCredits} credits.

			)
		}

		let enoughCredits = currentCredits >= neededCredits

		return (

				You have currently planned for {currentCredits} of your{' '}
				{neededCredits} required credits.
				{enoughCredits ? ' Good job!' : ''}

		)
	}
}
<commit_msg>remove stuff from StudentSummary<commit_after>// @flow

import React from 'react'
import cx from 'classnames'
import listify from 'listify'
import sample from 'lodash/sample'
import {Set} from 'immutable'
import {connect} from 'react-redux'
import {Card} from '../../components/card'
import {AvatarLetter} from '../../components/avatar-letter'
import {AutoSizedInput} from '../../components/autosize'
import {
	changeStudent,
	type ChangeStudentFunc,
} from '../../redux/students/actions/change'
import {Student, type AreaQuery} from '@gob/object-student'
import {checkStudentAgainstArea} from '../../workers/check-student'
import {loadArea} from '../../helpers/load-area'
import uniqueId from 'lodash/uniqueId'

import './student-summary.scss'

const welcomeMessages = [
	'Hi, ',
	'Hi there, ',
	'Hello, ',
	'こんにちは、', // japanese
	'ようこそ、', // japanese
	'Fram! Fram! ',
	'Salut, ',
	'Aloha, ', // hawaiian
	'Привет, ',
	'Вітаю, ',
	'Sawubona, ',
	'Hei, ',
	'Hola, ', // spanish
	'Bonjour, ', // french
	'Hallo, ', // german
	'nyob zoo ', // hmong
	'你好，', // mandarin
	'안녕하세요 ', // korean
	'สวัสดี ', // thai
	'halo, ', // indonesian
	'Salve, ', // latin
	'Χαῖρε! ', // ancient greek
]

const welcomeMessage = welcomeMessages[2]

type Props = {
	randomizeHello?: boolean,
	showAvatar?: boolean,
	showMessage?: boolean,
	student: Student,
}

type State = {
	message: string,
	canGraduate: boolean,
	creditsNeeded: ?number,
	creditsTaken: ?number,
	checking: boolean,
}

class StudentSummary extends React.Component<Props, State> {
	state = {
		message: this.props.randomizeHello
			? sample(welcomeMessages)
			: welcomeMessage,
		checking: true,
		canGraduate: false,
		creditsNeeded: null,
		creditsTaken: null,
	}

	componentDidMount() {
		this.checkGraduatability(this.props)
	}

	componentDidUpdate(prevProps: Props) {
		if (prevProps.student !== this.props.student) {
			this.checkGraduatability(this.props)
		}
	}

	checkGraduatability = async (props: Props) => {
		let {student} = props

		this.setState(() => ({checking: true}))

		let areas = student.studies.map(loadArea)
		let loadedAreas = (await Promise.all(areas))
			.filter(({error}) => !error)
			.map(({data}) => data)

		let promises = loadedAreas.map(a => checkStudentAgainstArea(student, a))
		let results = await Promise.all(promises)

		let canGraduate = results.every(r => r.computed === true)
		let {creditsNeeded = 0, creditsTaken = 0} = {}

		this.setState(() => ({
			checking: false,
			canGraduate,
			creditsNeeded,
			creditsTaken,
		}))
	}

	render() {
		let {student, showMessage = true, showAvatar = true} = this.props
		let {checking, canGraduate, creditsNeeded, creditsTaken} = this.state
		let {studies} = student
		let gradClassName = canGraduate ? 'can-graduate' : 'cannot-graduate'
		let message = this.state.message

		return (
			<Card
				as="article"
				className={cx('student-summary', gradClassName, {checking})}
			>
				<ConnectedEditor student={student} />

				{showAvatar && (
					<AvatarLetter
						className={cx(
							'student-letter',
							canGraduate ? 'can-graduate' : 'cannot-graduate',
						)}
						value={student.name}
					/>
				)}

				<DateSummary
					matriculation={student.matriculation}
					graduation={student.graduation}
				/>

				<DegreeSummary studies={studies} />

				<CreditSummary
					currentCredits={creditsTaken}
					neededCredits={creditsNeeded}
				/>

				{showMessage ?  : null}
			</Card>
		)
	}
}

export {StudentSummary}

type EditorProps = {
	student: Student,
	changeStudent: ChangeStudentFunc,
}

type EditorState = {
	name: string,
	matriculation: string,
	graduation: string,
}

class Editor extends React.Component<EditorProps, EditorState> {
	state = {
		name: this.props.student.name,
		matriculation: String(this.props.student.matriculation),
		graduation: String(this.props.student.graduation),
	}

	nameLabelId = `student-editor--${uniqueId()}`
	matriculationLabelId = `student-editor--${uniqueId()}`
	graduationLabelId = `student-editor--${uniqueId()}`

	changeName = (event: SyntheticInputEvent<HTMLInputElement>) => {
		let val = event.currentTarget.value
		this.setState(() => ({name: val}))
	}

	changeGraduation = (event: SyntheticInputEvent<HTMLInputElement>) => {
		let val = event.currentTarget.value
		this.setState(() => ({graduation: val}))
	}

	changeMatriculation = (event: SyntheticInputEvent<HTMLInputElement>) => {
		let val = event.currentTarget.value
		this.setState(() => ({matriculation: val}))
	}

	onSubmit = (event: SyntheticInputEvent<HTMLFormElement>) => {
		event.preventDefault()

		let {name, matriculation, graduation} = this.state
		let s = this.props.student

		if (matriculation !== s.matriculation) {
			s = s.setMatriculation(matriculation)
		}

		if (graduation !== s.graduation) {
			s = s.setGraduation(graduation)
		}

		if (name !== s.name) {
			s = s.setName(name)
		}

		if (s !== this.props.student) {
			this.props.changeStudent(s)
		}
	}

	render() {
		return (
			<form onSubmit={this.onSubmit} className="student-summary--editor">
				Name:
				<input
					id={this.nameLabelId}
					onChange={this.changeName}
					onBlur={this.onSubmit}
					value={this.state.name}
				/>

					Matriculation:

				<input
					id={this.matriculationLabelId}
					onChange={this.changeMatriculation}
					onBlur={this.onSubmit}
					value={this.state.matriculation}
				/>

				Graduation:
				<input
					id={this.graduationLabelId}
					onChange={this.changeGraduation}
					onBlur={this.onSubmit}
					value={this.state.graduation}
				/>
			</form>
		)
	}
}

const ConnectedEditor = connect(
	undefined,
	{changeStudent},
)(Editor)

type HeaderProps = {
	canGraduate: boolean,
	helloMessage: string,
	name: string,
	onChangeName?: string => any,
	showAvatar: boolean,
}

export class Header extends React.Component<HeaderProps> {
	handleNameChange = (val: string) => {
		console.log(val)
		this.props.onChangeName && this.props.onChangeName(val)
	}

	render() {
		const props = this.props

		return (

				{props.helloMessage}
				{String(this.props.name)}!

		)
	}
}

type FooterProps = {
	canGraduate: boolean,
}

const goodGraduationMessage =
	"It looks like you'll make it! Just follow the plan, and go over my output with your advisor a few times."
const badGraduationMessage =
	"You haven't planned everything out yet. Ask your advisor if you need help fitting everything in."

export class Footer extends React.Component<FooterProps> {
	render() {
		const msg = this.props.canGraduate
			? goodGraduationMessage
			: badGraduationMessage

		return
{msg}

	}
}

type DateSummaryProps = {
	matriculation: number,
	graduation: number,
}

export class DateSummary extends React.Component<DateSummaryProps> {
	render() {
		const props = this.props

		return (

				After matriculating in {String(props.matriculation)}, you are
				planning to graduate in {String(props.graduation)}.

		)
	}
}

type DegreeSummaryProps = {
	studies: Set<AreaQuery>,
}

export class DegreeSummary extends React.Component<DegreeSummaryProps> {
	render() {
		const grouped: {
			[key: string]: Set<{type: string, name: string, revision: string}>,
		} = this.props.studies.groupBy(s => s.type).toJSON()

		const {
			degree: dS = Set(),
			major: mS = Set(),
			concentration: cS = Set(),
			emphasis: eS = Set(),
		} = grouped

		const dCount = dS.size
		const mCount = mS.size
		const cCount = cS.size
		const eCount = eS.size

		const dWord = dCount === 1 ? 'degree' : 'degrees'
		const mWord = mCount === 1 ? 'major' : 'majors'
		const cWord = cCount === 1 ? 'concentration' : 'concentrations'
		const eWord = eCount === 1 ? 'emphasis' : 'emphases'

		const dEmph = dCount === 1 ? 'a ' : ''
		const mEmph = mCount === 1 ? 'a ' : ''
		const cEmph = cCount === 1 ? 'a ' : ''
		const eEmph = eCount === 1 ? 'an ' : ''

		const dList = listify([...dS.map(d => d.name)])
		const mList = listify([...mS.map(m => m.name)])
		const cList = listify([...cS.map(c => c.name)])
		const eList = listify([...eS.map(e => e.name)])

		return (

				You are planning on{' '}
				{dCount > 0 ? `${dEmph}${dList} ${dWord}` : `no ${dWord}`}
				{mCount || cCount || eCount
					? mCount && (cCount || eCount)
						? ', '
						: ' and '
					: ''}
				{mCount ? `${mEmph}${mWord} in ${mList}` : ''}
				{mCount && cCount ? ', and ' : ''}
				{cCount ? `${cEmph}${cWord} in ${cList}` : ''}
				{(mCount || cCount) && eCount ? ', ' : ''}
				{eCount ? `not to mention ${eEmph}${eWord} in ${eList}` : ''}
				{'.'}

		)
	}
}

type CreditSummaryProps = {
	currentCredits: ?number,
	neededCredits: ?number,
}

export class CreditSummary extends React.Component<CreditSummaryProps> {
	render() {
		let {currentCredits, neededCredits} = this.props

		if (currentCredits == null) {
			return null
		}

		if (neededCredits == null) {
			return (

					You have currently planned for {currentCredits} credits.

			)
		}

		let enoughCredits = currentCredits >= neededCredits

		return (

				You have currently planned for {currentCredits} of your{' '}
				{neededCredits} required credits.
				{enoughCredits ? ' Good job!' : ''}

		)
	}
}
<|endoftext|>


<commit_before>// Requires
const Discord = require('discord.js')
const fs = require('fs')
const config = require('./config.json');
// Create an instance of a Discord client
const client = new Discord.Client()

// The bot is ready
client.on('ready', () => {
  console.log('Bot Started')
})

client.on('message', (message) => {// when message is sent
  // Set the prefix
  let prefix = config.prefix;

  // Exit and stop if it's not there
  if (!message.content.startsWith(prefix) || message.author.bot) return;

  if (message.content ===("<>")){ // when message is <>
      message.channel.sendMessage("Shinies!"); // send running message into the channel where the message was sent
  }

  if (message.content.startsWith(prefix + 'help'))
  {
    message.channel.send('I don\'t know what to help with yet!');
  }
  else if (message.content.startsWith(prefix + 'idoruu'))
  {
    message.channel.send('http://i.imgur.com/Emk9LEb.png!');
  }

  else if(message.content.startsWith(config.prefix + 'prefix'))
  {
    // if it's not me it won't work
    if(message.author.id !== config.ownerID) return;
  // Gets the prefix from the command (eg. "!prefix +" it will take the "+" from it)
  let newPrefix = message.content.split(' ').slice(1, 2)[0];
  // change the configuration in memory
  config.prefix = newPrefix;

  // Now we have to save the file.
  fs.writeFile('./config.json', JSON.stringify(config), (err) => if(err) console.error(err));
  }
  else if(message.content.startsWith(config.prefix + 'waifu'))
  {
    // if it's not me it won't work
    if(message.author.id !== config.ownerID)
    {
      message.channel.send('Not AA-senpai go away');
    }
    else
    {
    message.channel.send('AA-senpai!');
    }

  }
})
client.login(process.env.BOT_TOKEN)
<commit_msg>removed prefix changer<commit_after>// Requires
const Discord = require('discord.js')
const fs = require('fs')
const config = require('./config.json');
// Create an instance of a Discord client
const client = new Discord.Client()

// The bot is ready
client.on('ready', () => {
  console.log('Bot Started')
})

client.on('message', (message) => {// when message is sent
  // Set the prefix
  let prefix = config.prefix;

  // Exit and stop if it's not there
  if (!message.content.startsWith(prefix) || message.author.bot) return;

  if (message.content ===("<>")){ // when message is <>
      message.channel.sendMessage("Shinies!"); // send running message into the channel where the message was sent
  }

  if (message.content.startsWith(prefix + 'help'))
  {
    message.channel.send('I don\'t know what to help with yet!');
  }
  else if (message.content.startsWith(prefix + 'idoruu'))
  {
    message.channel.send('http://i.imgur.com/Emk9LEb.png!');
  }

  /**else if(message.content.startsWith(config.prefix + 'prefix'))
  {
    // if it's not me it won't work
    if(message.author.id !== config.ownerID) return;
  // Gets the prefix from the command (eg. "!prefix +" it will take the "+" from it)
  let newPrefix = message.content.split(' ').slice(1, 2)[0];
  // change the configuration in memory
  config.prefix = newPrefix;

  // Now we have to save the file.
  fs.writeFile('./config.json', JSON.stringify(config), (err) => if(err) console.error(err));
}**/
  else if(message.content.startsWith(config.prefix + 'waifu'))
  {
    // if it's not me it won't work
    if(message.author.id !== config.ownerID)
    {
      message.channel.send('Not AA-senpai go away');
    }
    else
    {
    message.channel.send('AA-senpai!');
    }

  }
})
client.login(process.env.BOT_TOKEN)
<|endoftext|>


<commit_before>define(['d3', './queryview', '../listoverlay', '../uiutil', '../setinfo', '../config'], function (d3, queryView, ListOverlay, uiUtil, setInfo, config) {

  //var listOverlay = new ListOverlay();

  return {
    getFilterOverlayItems: function (constraintType, text) {
      function getConstraintInfo() {
        switch (constraintType) {
          case "name":
            return {label: text, value: text, category: "Name"};
            break;
          case "type":
            return {label: text, value: text, category: "Type"};
            break;
          case "set":
            return {
              label: setInfo.getSetLabel(text),
              value: text,
              id: text,
              setNodeLabel: config.getSetNodeLabel(setInfo.get(text)),
              category: "Set"
            };
            break;
          default:
            return;
        }
      }

      return [{
        text: "Must contain",
        icon: "\uf0b0",
        callback: function () {
          queryView.addNodeFilter(getConstraintInfo(), false);
        }
      },
        {
          text: "Must not contain",
          icon: "\uf0b0",
          callback: function () {
            queryView.addNodeFilter(getConstraintInfo(), true);
          }
        }
      ]
    }
  }
});
<commit_msg>added context entries for setting start and end node, wip<commit_after>define(['d3', './queryview', '../listoverlay', '../uiutil', '../setinfo', '../config'], function (d3, queryView, ListOverlay, uiUtil, setInfo, config) {

    //var listOverlay = new ListOverlay();

    return {
        getFilterOverlayItems: function (constraintType, text) {
            function getConstraintInfo() {
                switch (constraintType) {
                    case "name":
                        return {label: text, value: text, category: "Name"};
                        break;
                    case "type":
                        return {label: text, value: text, category: "Type"};
                        break;
                    case "set":
                        return {
                            label: setInfo.getSetLabel(text),
                            value: text,
                            id: text,
                            setNodeLabel: config.getSetNodeLabel(setInfo.get(text)),
                            category: "Set"
                        };
                        break;
                    default:
                        return;
                }
            }

            return [
                {
                    text: "Must contain",
                    icon: "\uf0b0",
                    callback: function () {
                        queryView.addNodeFilter(getConstraintInfo(), false);
                    }
                },
                {
                    text: "Must not contain",
                    icon: "\uf0b0",
                    callback: function () {
                        queryView.addNodeFilter(getConstraintInfo(), true);
                    }
                },
                {
                    text: "As start",
                    icon: "\uf0b0",
                    callback: function () {
                        queryView.addNodeFilter(getConstraintInfo(), false);
                    }
                },
                {
                    text: "As end",
                    icon: "\uf0b0",
                    callback: function () {
                        queryView.addNodeFilter(getConstraintInfo(), true);
                    }
                }
            ]
        }
    }
});
<|endoftext|>


<commit_before>import moment from 'moment'
import chalk from 'chalk'
import format from '../time'
import pad from 'pad/lib/colors'
import Entry from 'tickbin-entry-parser'
import { hashPattern } from 'tickbin-entry-parser'

export { writeSaved }
export { writeRemove }
export {getOutputs as getOutputs}

function writeSaved (doc) {
  const entry = Entry.fromJSON(doc)
  const { detailed } = getOutputs(entry)
  console.log(chalk.bgGreen('+'), detailed)
}

function writeRemove (doc) {
  const entry = Entry.fromJSON(doc)
  const { detailed } = getOutputs(entry)
  console.log(chalk.bgRed('-'), detailed)
}

function getOutputs(entry) {
  const timePattern = new RegExp(/\s*/.source + entry.time + /\s*/.source, 'g')
  const id = chalk.gray(entry._id)
  const date = chalk.yellow(moment(entry.start).format('ddd MMM DD'))
  const timeStart = moment(entry.start)
  const timeEnd = moment(entry.end)
  const time = `${timeStart.format('hh:mma')}-${timeEnd.format('hh:mma')}`
  const duration = format(entry.duration.minutes)
  const seconds = entry.duration.seconds
  const msg = entry.message
    .replace(hashPattern, chalk.cyan('$1'))
    .replace(timePattern, ' ')
    .trim()
  const tags = chalk.cyan([...entry.tags].join(' '))
  const icon = chalk.gray(' ') // TODO: make this reflect sync state

  const detailed = `${pad(id, 9)} ${pad(date, 9)} ${time} ${duration} ${msg}`
  const simple = `${pad(id, 9)} ${time} ${duration} ${msg}`

  return {id, date, seconds, msg, tags, icon, detailed, simple}
}
<commit_msg>Green backround of + in commit changed to green +<commit_after>import moment from 'moment'
import chalk from 'chalk'
import format from '../time'
import pad from 'pad/lib/colors'
import Entry from 'tickbin-entry-parser'
import { hashPattern } from 'tickbin-entry-parser'

export { writeSaved }
export { writeRemove }
export {getOutputs as getOutputs}

function writeSaved (doc) {
  const entry = Entry.fromJSON(doc)
  const { detailed } = getOutputs(entry)
  console.log(chalk.green('+'), detailed)
}

function writeRemove (doc) {
  const entry = Entry.fromJSON(doc)
  const { detailed } = getOutputs(entry)
  console.log(chalk.bgRed('-'), detailed)
}

function getOutputs(entry) {
  const timePattern = new RegExp(/\s*/.source + entry.time + /\s*/.source, 'g')
  const id = chalk.gray(entry._id)
  const date = chalk.yellow(moment(entry.start).format('ddd MMM DD'))
  const timeStart = moment(entry.start)
  const timeEnd = moment(entry.end)
  const time = `${timeStart.format('hh:mma')}-${timeEnd.format('hh:mma')}`
  const duration = format(entry.duration.minutes)
  const seconds = entry.duration.seconds
  const msg = entry.message
    .replace(hashPattern, chalk.cyan('$1'))
    .replace(timePattern, ' ')
    .trim()
  const tags = chalk.cyan([...entry.tags].join(' '))
  const icon = chalk.gray(' ') // TODO: make this reflect sync state

  const detailed = `${pad(id, 9)} ${pad(date, 9)} ${time} ${duration} ${msg}`
  const simple = `${pad(id, 9)} ${time} ${duration} ${msg}`

  return {id, date, seconds, msg, tags, icon, detailed, simple}
}
<|endoftext|>


<commit_before>function FreeWillStuff(session){
	this.session = session;
	this.canRepeat = true;
	this.playerList = [];  //what players are already in the medium when i trigger?
	this.decision = null
	//luck can be good or it can be bad.
	//should something special happen if you have a lot of negative free will? like...
	//maybe exile shenanigans?
	this.trigger = function(playerList){
		this.decision = null;//reset
		//what the hell roue of doom's corpse. corpses aren't part of the player list!
		for(var i = 0; i<this.session.availablePlayers.length; i++){
			var player = this.session.availablePlayers[i];
			if(player.freeWill > 25){  //don't even get to consider a decision if you don't have  more than default free will.
				var decision = this.getPlayerDecision(player);
				if(decision){
					var d = new WillPower(player, decision)
					if(!this.decision || d.player.freeWill > this.decision.player.freeWill){  //whoever has the most will makes the decision.
						this.decision = d;
					}
				}
			}
		}
		return this.decision != null;
	}

	this.renderContent = function(div){
		div.append("
"+this.content());
	}

	//in murder mode, plus random. reduce trigger, too. only for self (whether active or passive)
	//more likely if who you hate is ectobiologist or space
	this.considerDisEngagingMurderMode = function(player){
		if(player.murderMode){
				var ret = "";
				var enemies = player.getEnemiesFromList(findLivingPlayers(this.session.players));
				var spacePlayerEnemy = findAspectPlayer(enemies, "Space");
				var ectobiologistEnemy = getLeader(enemies);
				//not everybody knows about ectobiology.
				if(!this.session.ectoBiologyStarted && ectobiologistEnemy && player.knowsAboutSburb()){
					console.log("Free will stop from killing ectobiologist: " + this.session.session_id);
					ret += "With a conscious act of will, the " + player.htmlTitle() + "settles their shit. If this keeps up, they are going to end up killing the " + ectobiologistEnemy.htmlTitle();
					ret += " and then they will NEVER do ectobiology.  No matter HOW much of an asshole they are, it's not worth dooming the timeline. ";
					player.murderMode = false;
					player.leftMurderMode = true;
					player.triggerLevel = 0; //
					return ret;
				}
				//not everybody knows why frog breeding is important.
				if(spacePlayerEnemy && spacePlayerEnemy.landLevel < this.session.goodFrogLevel  && player.knowsAboutSburb()){
					console.log("Free will stop from killing space player: " + this.session.session_id);
					ret += "With a conscious act of will, the " + player.htmlTitle() + "settles their shit. If this keeps up, they are going to end up killing the " + spacePlayerEnemy.htmlTitle();
					ret += " and then they will NEVER have frog breeding done. They can always kill them AFTER they've escaped to the new Universe, right? ";
					player.murderMode = false;
					player.leftMurderMode = true;
					player.triggerLevel = 0; //
					return ret;
				}
				//NOT luck. just obfuscated reasons.
				if(Math.seededRandom() > 0.5){
					console.log("Free will stop from killing everybody: " + this.session.session_id);
					ret += "With a conscious act of will, the " + player.htmlTitle() + "settles their shit. No matter HOW much of an asshole people are, SBURB is the true enemy, and they are not going to let themselves forget that. ";
					player.murderMode = false;
					player.leftMurderMode = true;
					player.triggerLevel = 0; //
					return ret;
				}
		}
		return null;
	}

  //if you know better, you won't doom the session.
	this.isValidTargets(enemies){
		var spacePlayerEnemy = findAspectPlayer(enemies, "Space");
		var ectobiologistEnemy = getLeader(enemies);
		if(spacePlayerEnemy && spacePlayerEnemy.landLevel < this.session.goodFrogLevel  && player.knowsAboutSburb()){
			return false;
		}
		if(!this.session.ectoBiologyStarted && ectobiologistEnemy && player.knowsAboutSburb()){
				return false;
		}

		return true;
	}

	//hate someone, not in murder mode, self if active, other if passive. plus random, increase trigger, too. if you engage murder mode in someone else, random chance to succesfully manipulate them to hate who you hate.
	//less likely if who you hate is ectobiologist or space
	this.considerEngagingMurderMode = function(player){
		var enemies = player.getEnemiesFromList(findLivingPlayers(this.session.players));
		if(player.isActive() && enemies.length > 0 && player.triggerLevel > 3){
			return becomeMurderMode(player);
		}else if(enemies.length > 0 && player.triggerLevel > 3){
			return forceSomeOneElseMurderMode(player);
		}
		return null;
	}
	//i'm not in murder mode. it's not a terrible idea to kill my enemies.
	this.becomeMurderMode = function(player){
		if(!player.murderMode){
			var enemies = player.getEnemiesFromList(findLivingPlayers(this.session.players));
			if(this.isValidTargets(enemies)){
					console.log("chosing to go into murdermode " +this.session.session_id);
					player.murderMode = true;  //no font change. not crazy. obviously. why would you think they were?
					player.triggerLevel = 10;
					//harry potter and the methods of rationality to the rescue
					return "The " + player.htmlTitleBasic() + " has thought things through. They are not crazy. To the contrary, they feel so sane it burns like ice. It's SBURB that's crazy.  Surely anyone can see this? The only logical thing left to do is kill everyone to save them from their terrible fates. And if they happen to start with the assholes...well, baby steps. It's not every day they extinguish an entire species. ";
			}
		}
		return null;
	}

	//find someone not in the list of enemies. choose whoever is enemies with the most amount of given enemies but not the player.
	this.findBestPatsy = function(player, enemies){

	}

	//thief/prince/maage/witch of mind.
	this.canStealWills = function(){

	}

	//thief/prince of blood. thief/prince of heart. mage/witch of rage.
	this.canInfluenceEnemies = function(){

	}

	//it's not a terrible idea to kill my enemies, and I can find someone not already in murder mode.
	//random chance of making my enemies their enemies. boosted if prince/thief of mind or blood. or witch/mage or rage? special dialogue if so.
	//have method to look for best patsy. (best one is someone who isn't already your enemy who hates the most amount of your enemies.)
	//only do mind control if whoever you pick hates less than half of who you hate.
	this.forceSomeOneElseMurderMode = function(player){
		var enemies = player.getEnemiesFromList(findLivingPlayers(this.session.players));
		var patsyArr = findBestPatsy(player, enemies);
		var patsy = patsyArr[0];
		var patsyVal = patsyArr[1];
		if(this.isValidTargets(enemies) && patsy){
				if(patsyVal > enemies.length/2 && patasy.triggerLevel > 1){
						console.log("manipulating someone to go into murdermode " +this.session.session_id);
						patsy.murderMode = true;
						return "The " + player.htmlTitleBasic() + " has thought things through. They are not crazy. To the contrary, they feel so sane it burns like ice. It's SBURB that's crazy.  Surely anyone can see this? The only logical thing left to do is kill everyone to save them from their terrible fates. They use clever words to convince the " + patsy.htmlTitleBasic() + " of the righteousness of their plan. They agree to carry out the bloody work. ";

				}else if(canStealWills(player) && patsy.freeWill * 2 < player.freeWill){  //can't steal your will if you have enough of it.
					console.log("mind controling someone to go into murdermode and altering their enemies with game powers." +this.session.session_id);
					patsy.murderMode = true;
					patsy.triggerLevel = 10;
					this.alterEnemies(patsy, enemies,player);
					return "The " + player.htmlTitleBasic() + " has thought things through. They are not crazy. To the contrary, they feel so sane it burns like ice. It's SBURB that's crazy.  Surely anyone can see this? The only logical thing left to do is kill everyone to save them from their terrible fates. They use game powers to manipulate the very will of the " + patsy.htmlTitleBasic() + " and use them as a weapon. This is completely terrifying.  ";
				}else if(canInfluenceEnemies(player) && patsy.freeWill * 2 < player.freeWill){
					console.log("rage controling into murdermode and altering their enemies with game powers." +this.session.session_id);
					patsy.murderMode = true;
					patsy.triggerLevel = 10;
					this.alterEnemies(patsy, enemies,player);
					var modifiedTrait = "relationships"
					if(player.aspect == "Heart") modifiedTrait = "identity"
					if(player.aspect == "Rage") modifiedTrait = "sanity"
					return "The " + player.htmlTitleBasic() + " has thought things through. They are not crazy. To the contrary, they feel so sane it burns like ice. It's SBURB that's crazy.  Surely anyone can see this? The only logical thing left to do is kill everyone to save them from their terrible fates. They use game powers to manipulate the " + patsy.htmlTitleBasic() + "'s " + modifiedTrait + " until they are willing to carry out their plan. This is completely terrifying. ";
				}
		}
		return null;
	}

	// do it to self if active, do it to someone else if not.  need to have it not be destiny. bonus if there are dead players (want to avenge them/stop more corpses).
	this.considerForceGodTier = function(player){

	}

	//needs to be a murder mode player. more likely if you like them.  if active and you like them a lot, do it yourself. if passive, see if you can get somebody else to do it for you (mastermind)
	//more likely if murderMode player is ectobiologist or space
	this.considerCalmMurderModePlayer = function(player){

	}

	//needs to be a murdermode player,  more likely if you dislike them. if active, do it yourself, if passive, see if you can get somebody else to do it for you. need to be stronger than them.
	//less likely if murderMode player is ectobiologist or space
	this.considerKillMurderModePlayer = function(player){

	}

	//if self, just fucking do it. otherwise, pester them. raise power to min requirement, if it's not already there.
	this.considerMakingEctobiologistDoJob = function(player){

	}

	//if self, just fucking do it. raise land level. otherwise, pester them. raise power to min requirement, if it's not already there.
	this.considerMakingSpacePlayerDoJob = function(player){

	}

	this.getPlayerDecision = function(player){
		//reorder things to change prevelance.
		var ret = this.considerCalmMurderModePlayer(player);
		if(ret == null) ret = this.considerKillMurderModePlayer(player);
		if(ret == null) ret = this.considerDisEngagingMurderMode(player);
		if(ret == null) ret = this.considerEngagingMurderMode(player);
		if(ret == null) ret = this.considerMakingEctobiologistDoJob(player);
		if(ret == null) ret = this.considerMakingSpacePlayerDoJob(player);
		if(ret == null) ret = this.considerForceGodTier(player);
		return ret;
	}

	this.processDecision = function(){

	}

	this.content = function(){
		console.log("Decision event: " + this.session.session_id)
		var ret = "Decision Event: ";
		removeFromArray(this.player, this.session.availablePlayers);
		for(var i = 0; i<this.wills.length; i++){
			var will = this.wills[i];
			removeFromArray(will.player, this.session.availablePlayers);
			ret += this.processDecision(will);
		}

		return ret;
	}
}

function WillPower(player, decision){
	this.player = player;
	this.decision = decision;
}
<commit_msg>almost done coding mind control murders. not gonna test till everything is ready, tho<commit_after>function FreeWillStuff(session){
	this.session = session;
	this.canRepeat = true;
	this.playerList = [];  //what players are already in the medium when i trigger?
	this.decision = null
	//luck can be good or it can be bad.
	//should something special happen if you have a lot of negative free will? like...
	//maybe exile shenanigans?
	this.trigger = function(playerList){
		this.decision = null;//reset
		//what the hell roue of doom's corpse. corpses aren't part of the player list!
		for(var i = 0; i<this.session.availablePlayers.length; i++){
			var player = this.session.availablePlayers[i];
			if(player.freeWill > 25){  //don't even get to consider a decision if you don't have  more than default free will.
				var decision = this.getPlayerDecision(player);
				if(decision){
					var d = new WillPower(player, decision)
					if(!this.decision || d.player.freeWill > this.decision.player.freeWill){  //whoever has the most will makes the decision.
						this.decision = d;
					}
				}
			}
		}
		return this.decision != null;
	}

	this.renderContent = function(div){
		div.append("
"+this.content());
	}

	//in murder mode, plus random. reduce trigger, too. only for self (whether active or passive)
	//more likely if who you hate is ectobiologist or space
	this.considerDisEngagingMurderMode = function(player){
		if(player.murderMode){
				var ret = "";
				var enemies = player.getEnemiesFromList(findLivingPlayers(this.session.players));
				var spacePlayerEnemy = findAspectPlayer(enemies, "Space");
				var ectobiologistEnemy = getLeader(enemies);
				//not everybody knows about ectobiology.
				if(!this.session.ectoBiologyStarted && ectobiologistEnemy && player.knowsAboutSburb()){
					console.log("Free will stop from killing ectobiologist: " + this.session.session_id);
					ret += "With a conscious act of will, the " + player.htmlTitle() + "settles their shit. If this keeps up, they are going to end up killing the " + ectobiologistEnemy.htmlTitle();
					ret += " and then they will NEVER do ectobiology.  No matter HOW much of an asshole they are, it's not worth dooming the timeline. ";
					player.murderMode = false;
					player.leftMurderMode = true;
					player.triggerLevel = 0; //
					return ret;
				}
				//not everybody knows why frog breeding is important.
				if(spacePlayerEnemy && spacePlayerEnemy.landLevel < this.session.goodFrogLevel  && player.knowsAboutSburb()){
					console.log("Free will stop from killing space player: " + this.session.session_id);
					ret += "With a conscious act of will, the " + player.htmlTitle() + "settles their shit. If this keeps up, they are going to end up killing the " + spacePlayerEnemy.htmlTitle();
					ret += " and then they will NEVER have frog breeding done. They can always kill them AFTER they've escaped to the new Universe, right? ";
					player.murderMode = false;
					player.leftMurderMode = true;
					player.triggerLevel = 0; //
					return ret;
				}
				//NOT luck. just obfuscated reasons.
				if(Math.seededRandom() > 0.5){
					console.log("Free will stop from killing everybody: " + this.session.session_id);
					ret += "With a conscious act of will, the " + player.htmlTitle() + "settles their shit. No matter HOW much of an asshole people are, SBURB is the true enemy, and they are not going to let themselves forget that. ";
					player.murderMode = false;
					player.leftMurderMode = true;
					player.triggerLevel = 0; //
					return ret;
				}
		}
		return null;
	}

  //if you know better, you won't doom the session.
	this.isValidTargets(enemies){
		var spacePlayerEnemy = findAspectPlayer(enemies, "Space");
		var ectobiologistEnemy = getLeader(enemies);
		if(spacePlayerEnemy && spacePlayerEnemy.landLevel < this.session.goodFrogLevel  && player.knowsAboutSburb()){
			return false;
		}
		if(!this.session.ectoBiologyStarted && ectobiologistEnemy && player.knowsAboutSburb()){
				return false;
		}

		return true;
	}

	//hate someone, not in murder mode, self if active, other if passive. plus random, increase trigger, too. if you engage murder mode in someone else, random chance to succesfully manipulate them to hate who you hate.
	//less likely if who you hate is ectobiologist or space
	this.considerEngagingMurderMode = function(player){
		var enemies = player.getEnemiesFromList(findLivingPlayers(this.session.players));
		if(player.isActive() && enemies.length > 0 && player.triggerLevel > 3){
			return becomeMurderMode(player);
		}else if(enemies.length > 0 && player.triggerLevel > 3){
			return forceSomeOneElseMurderMode(player);
		}
		return null;
	}
	//i'm not in murder mode. it's not a terrible idea to kill my enemies.
	this.becomeMurderMode = function(player){
		if(!player.murderMode){
			var enemies = player.getEnemiesFromList(findLivingPlayers(this.session.players));
			if(this.isValidTargets(enemies)){
					console.log("chosing to go into murdermode " +this.session.session_id);
					player.murderMode = true;  //no font change. not crazy. obviously. why would you think they were?
					player.triggerLevel = 10;
					//harry potter and the methods of rationality to the rescue
					return "The " + player.htmlTitleBasic() + " has thought things through. They are not crazy. To the contrary, they feel so sane it burns like ice. It's SBURB that's crazy.  Surely anyone can see this? The only logical thing left to do is kill everyone to save them from their terrible fates. And if they happen to start with the assholes...well, baby steps. It's not every day they extinguish an entire species. ";
			}
		}
		return null;
	}

	//find someone not in the list of enemies. choose whoever is enemies with the most amount of given enemies but not the player.
	this.findBestPatsy = function(player, enemies){

	}

	//thief/bard/maage/witch of mind.
	this.canStealWills = function(player){
		if(player.aspect == "Mind"){
			if(player.class_name == "Thief" || player.class_name == "Mage" || player.class_name == "Bard" || player.class_name == "Witch"){
				return true;
			}
		}
		return false;

	}

	//thief/prince/mage/witch of blood. thief/prince/mage/witch of heart. /mage/witch of rage.
	this.canInfluenceEnemies = function(player){
		if(player.aspect == "Blood"){
			if(player.class_name == "Thief" || player.class_name == "Mage" || player.class_name == "Bard" || player.class_name == "Witch"){
				return true;
			}
		}

		if(player.aspect == "Rage"){
			if( player.class_name == "Mage" || player.class_name == "Witch"){
				return true;
			}

		}
		return false;

	}

	//it's not a terrible idea to kill my enemies, and I can find someone not already in murder mode.
	//random chance of making my enemies their enemies. boosted if prince/thief of mind or blood. or witch/mage or rage? special dialogue if so.
	//have method to look for best patsy. (best one is someone who isn't already your enemy who hates the most amount of your enemies.)
	//only do mind control if whoever you pick hates less than half of who you hate.
	this.forceSomeOneElseMurderMode = function(player){
		var enemies = player.getEnemiesFromList(findLivingPlayers(this.session.players));
		var patsyArr = findBestPatsy(player, enemies);
		var patsy = patsyArr[0];
		var patsyVal = patsyArr[1];
		if(this.isValidTargets(enemies) && patsy){
				if(patsyVal > enemies.length/2 && patasy.triggerLevel > 1){
						console.log("manipulating someone to go into murdermode " +this.session.session_id);
						patsy.murderMode = true;
						return "The " + player.htmlTitleBasic() + " has thought things through. They are not crazy. To the contrary, they feel so sane it burns like ice. It's SBURB that's crazy.  Surely anyone can see this? The only logical thing left to do is kill everyone to save them from their terrible fates. They use clever words to convince the " + patsy.htmlTitleBasic() + " of the righteousness of their plan. They agree to carry out the bloody work. ";

				}else if(canStealWills(player) && patsy.freeWill * 2 < player.freeWill){  //can't steal your will if you have enough of it.
					console.log("mind controling someone to go into murdermode and altering their enemies with game powers." +this.session.session_id);
					patsy.murderMode = true;
					patsy.triggerLevel = 10;
					var rage = this.alterEnemies(patsy, enemies,player);
					return "The " + player.htmlTitleBasic() + " has thought things through. They are not crazy. To the contrary, they feel so sane it burns like ice. It's SBURB that's crazy.  Surely anyone can see this? The only logical thing left to do is kill everyone to save them from their terrible fates. They use game powers to manipulate the very will of the " + patsy.htmlTitleBasic() + " and use them as a weapon. This is completely terrifying.  " + rage;
				}else if(canInfluenceEnemies(player) && patsy.freeWill * 2 < player.freeWill){
					console.log("rage controling into murdermode and altering their enemies with game powers." +this.session.session_id);
					patsy.murderMode = true;
					patsy.triggerLevel = 10;
					var rage = this.alterEnemies(patsy, enemies,player);
					var modifiedTrait = "relationships"
					if(player.aspect == "Heart") modifiedTrait = "identity"
					if(player.aspect == "Rage") modifiedTrait = "sanity"
					return "The " + player.htmlTitleBasic() + " has thought things through. They are not crazy. To the contrary, they feel so sane it burns like ice. It's SBURB that's crazy.  Surely anyone can see this? The only logical thing left to do is kill everyone to save them from their terrible fates. They use game powers to manipulate the " + patsy.htmlTitleBasic() + "'s " + modifiedTrait + " until they are willing to carry out their plan. This is completely terrifying. " + rage;
				}
		}
		return null;
	}

	//my enemies are your enemies.
	this.alterEnemies = function(patsy, enemies,player){
			for(var i = 0; i< enemies.length; i++){
				var enemy = enemies[i];
				if(enemy != patsy){//maybe i SHOULD reneable self-relationships. maybe you hate yourself? try to kill yourself?
					var r1 = player.getRelationshipWith(enemies[i]);
					var r2 = patsy.getRelationshipWith(enemies[i]);
					r2.value = r1.value;
				}
			}
			//hate you for doing this to me.
			var r = patsy.getRelationshipWith(player)
			var rage = 0;
			if (patsy.freeWill > 0) rage = -3;
			if (patsy.freeWill > 50) rage = -9;
			r.value += rage;
			var ret = ""
			if(rage < -3) ret = "The " + patsy.htmlTitle() + " seems to be upset about this, underneath the control.";
			if(rage < -9) ret = "The " + patsy.htmlTitle() + " is barely under control. They seem furious. ";
			return ret;
	}

	// do it to self if active, do it to someone else if not.  need to have it not be destiny. bonus if there are dead players (want to avenge them/stop more corpses).
	//sedoku reference???
	this.considerForceGodTier = function(player){

	}

	//needs to be a murder mode player. more likely if you like them.  if active and you like them a lot, do it yourself. if passive, see if you can get somebody else to do it for you (mastermind)
	//more likely if murderMode player is ectobiologist or space
	this.considerCalmMurderModePlayer = function(player){

	}

	//needs to be a murdermode player,  more likely if you dislike them. if active, do it yourself, if passive, see if you can get somebody else to do it for you. need to be stronger than them.
	//less likely if murderMode player is ectobiologist or space
	this.considerKillMurderModePlayer = function(player){

	}

	//if self, just fucking do it. otherwise, pester them. raise power to min requirement, if it's not already there.
	this.considerMakingEctobiologistDoJob = function(player){

	}

	//if self, just fucking do it. raise land level. otherwise, pester them. raise power to min requirement, if it's not already there.
	this.considerMakingSpacePlayerDoJob = function(player){

	}

	this.getPlayerDecision = function(player){
		//reorder things to change prevelance.
		var ret = this.considerCalmMurderModePlayer(player);
		if(ret == null) ret = this.considerKillMurderModePlayer(player);
		if(ret == null) ret = this.considerDisEngagingMurderMode(player);
		if(ret == null) ret = this.considerEngagingMurderMode(player);
		if(ret == null) ret = this.considerMakingEctobiologistDoJob(player);
		if(ret == null) ret = this.considerMakingSpacePlayerDoJob(player);
		if(ret == null) ret = this.considerForceGodTier(player);
		return ret;
	}

	this.processDecision = function(){

	}

	this.content = function(){
		console.log("Decision event: " + this.session.session_id)
		var ret = "Decision Event: ";
		removeFromArray(this.player, this.session.availablePlayers);
		for(var i = 0; i<this.wills.length; i++){
			var will = this.wills[i];
			removeFromArray(will.player, this.session.availablePlayers);
			ret += this.processDecision(will);
		}

		return ret;
	}
}

function WillPower(player, decision){
	this.player = player;
	this.decision = decision;
}
<|endoftext|>


<commit_before>// Requires
const Discord = require('discord.js')
const fs = require('fs')
const config = require('./config.json');
// Create an instance of a Discord client
const client = new Discord.Client()
// The bot is ready
client.on('ready', () => {
  console.log('Bot Started')
})

client.on('message', (message) => {// when message is sent
  // Set the prefix
  if (env.SELF_BOT=='TRUE') prefix=="AA";
  else
  {
    let prefix = config.prefix;
  }

  if (env.SELF_BOT=='TRUE')
  {
    if(message.author.id !== config.ownerID) return;
  }
  else
  {
    if(message.author.bot)return;
  }
  // Exit and stop if it's not there
  if (!message.content.startsWith(prefix)) return;

  if (message.content ===("<>")){ // when message is <>
      message.channel.send("Shinies!"); // send running message into the channel where the message was sent
  }

  else if(message.content.startsWith(config.prefix + 'prefix'))
  {
    // if it's not me it won't work
    if(message.author.id !== config.ownerID) return;
  // Gets the prefix from the command (eg. "!prefix +" it will take the "+" from it)
  let newPrefix = message.content.split(' ').slice(1, 2)[0];
  // change the configuration in memory
  config.prefix = newPrefix;

  // Now we have to save the file.
  fs.writeFile('./config.json', JSON.stringify(config));
}
  else if(message.content.startsWith(config.prefix + 'waifu'))
  {
    // if it's not me it won't work
    if(message.author.id !== config.ownerID)
    {
      message.channel.send('Not AA-senpai go away');
    }
    else
    {
    message.channel.send('AA-senpai!');
    }

  }
  else if(message.content.startsWith(config.prefix + 'terracolor'))
  {
      if(message.author.id !== '227596952852758528')
      {
        message.channel.send('Not Terra-senpai go away');
      }
      else
      {
        let args = message.content.split(' ').slice(1);
        let cleaned = args.split('#').slice(1);
          let terracolor = '#'+cleaned[0];

        message.guild.roles.find('name', 'Terra').setColor(terracolor);
        message.channel.send('Here you go~!');
      }

  }
  var commands=[
  ['help','I don\'t know what to help with yet! For now, though, I think I can: *idoruu*, *ruumove*,*heruusy*, and *ruuyear*!'],
  ['idoruu','http://i.imgur.com/Emk9LEb.png'],
  ['ruumove','http://i.imgur.com/49dk6gD.png'],
  ['heruusy','http://i.imgur.com/Hdcsu8e.jpg'],
  ['ruuyear','http://i.imgur.com/c6cfRd1.png'],
  ['clear','It\'s prunes, not clear!']
];
  for( i =  0; i<commands.length;i++)
  {
    if (message.content.startsWith(prefix + commands[i][0]))
    {
      message.channel.send(commands[i][1]);
    }

  }
  const params = message.content.split(' ').slice(1);
  if (message.content.startsWith(prefix + 'prune')) {
    // get number of messages to prune
    let messagecount = parseInt(params[0]);
    // get the channel logs
    if(message.author.id !== config.ownerID)
    {
      message.channel.send('Not AA-senpai, authorization denied');
    }
    else
    {
    message.channel.fetchMessages({
        limit: 100
      })
      .then(messages => {
        let msg_array = messages.array();
        // filter the message to only your own
        msg_array = msg_array.filter(m => m.author.id === client.user.id);
        // limit to the requested number + 1 for the command message
        msg_array.length = messagecount + 1;
        // Has to delete messages individually. Cannot use `deleteMessages()` on selfbots.
        msg_array.map(m => m.delete().catch(console.error));
        message.channel.send(messagecount+' messages deleted.');
      })
    }
  }
})
client.login(process.env.BOT_TOKEN)
<commit_msg>trying to figure out how env works<commit_after>// Requires
const Discord = require('discord.js')
const fs = require('fs')
const config = require('./config.json');
// Create an instance of a Discord client
const client = new Discord.Client()
// The bot is ready
client.on('ready', () => {
  console.log('Bot Started')
})

client.on('message', (message) => {// when message is sent
  // Set the prefix
  if (SELF_BOT=='TRUE') prefix=="AA";
  else
  {
    let prefix = config.prefix;
  }

  if (SELF_BOT=='TRUE')
  {
    if(message.author.id !== config.ownerID) return;
  }
  else
  {
    if(message.author.bot)return;
  }
  // Exit and stop if it's not there
  if (!message.content.startsWith(prefix)) return;

  if (message.content ===("<>")){ // when message is <>
      message.channel.send("Shinies!"); // send running message into the channel where the message was sent
  }

  else if(message.content.startsWith(config.prefix + 'prefix'))
  {
    // if it's not me it won't work
    if(message.author.id !== config.ownerID) return;
  // Gets the prefix from the command (eg. "!prefix +" it will take the "+" from it)
  let newPrefix = message.content.split(' ').slice(1, 2)[0];
  // change the configuration in memory
  config.prefix = newPrefix;

  // Now we have to save the file.
  fs.writeFile('./config.json', JSON.stringify(config));
}
  else if(message.content.startsWith(config.prefix + 'waifu'))
  {
    // if it's not me it won't work
    if(message.author.id !== config.ownerID)
    {
      message.channel.send('Not AA-senpai go away');
    }
    else
    {
    message.channel.send('AA-senpai!');
    }

  }
  else if(message.content.startsWith(config.prefix + 'terracolor'))
  {
      if(message.author.id !== '227596952852758528')
      {
        message.channel.send('Not Terra-senpai go away');
      }
      else
      {
        let args = message.content.split(' ').slice(1);
        let cleaned = args.split('#').slice(1);
          let terracolor = '#'+cleaned[0];

        message.guild.roles.find('name', 'Terra').setColor(terracolor);
        message.channel.send('Here you go~!');
      }

  }
  var commands=[
  ['help','I don\'t know what to help with yet! For now, though, I think I can: *idoruu*, *ruumove*,*heruusy*, and *ruuyear*!'],
  ['idoruu','http://i.imgur.com/Emk9LEb.png'],
  ['ruumove','http://i.imgur.com/49dk6gD.png'],
  ['heruusy','http://i.imgur.com/Hdcsu8e.jpg'],
  ['ruuyear','http://i.imgur.com/c6cfRd1.png'],
  ['clear','It\'s prunes, not clear!']
];
  for( i =  0; i<commands.length;i++)
  {
    if (message.content.startsWith(prefix + commands[i][0]))
    {
      message.channel.send(commands[i][1]);
    }

  }
  const params = message.content.split(' ').slice(1);
  if (message.content.startsWith(prefix + 'prune')) {
    // get number of messages to prune
    let messagecount = parseInt(params[0]);
    // get the channel logs
    if(message.author.id !== config.ownerID)
    {
      message.channel.send('Not AA-senpai, authorization denied');
    }
    else
    {
    message.channel.fetchMessages({
        limit: 100
      })
      .then(messages => {
        let msg_array = messages.array();
        // filter the message to only your own
        msg_array = msg_array.filter(m => m.author.id === client.user.id);
        // limit to the requested number + 1 for the command message
        msg_array.length = messagecount + 1;
        // Has to delete messages individually. Cannot use `deleteMessages()` on selfbots.
        msg_array.map(m => m.delete().catch(console.error));
        message.channel.send(messagecount+' messages deleted.');
      })
    }
  }
})
client.login(process.env.BOT_TOKEN)
<|endoftext|>


<commit_before>import React from 'react/addons';
import classNames from 'classnames';
import GeminiScrollbar from 'react-gemini-scrollbar';

import * as Util from '../Util/Util';

const CSSTransitionGroup = React.addons.CSSTransitionGroup;
const METHODS_TO_BIND = ['handleWindowResize', 'handleBackdropClick', 'closeModal'];

export default class Modal extends React.Component {
  constructor() {
    super();

    METHODS_TO_BIND.forEach(function (method) {
      this[method] = this[method].bind(this);
    }, this);
  }

  componentDidUpdate() {
    this.renderModal();
  }

  componentDidMount() {
    this.forceUpdate();

    window.addEventListener('resize', this.handleWindowResize);
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleWindowResize);
  }

  shouldComponentUpdate(nextProps) {
    return nextProps.open !== this.props.open;
  }

  handleBackdropClick() {
    if (this.props.closeByBackdropClick) {
      this.closeModal();
    }
  }

  handleWindowResize() {
    this.renderModal();
  }

  closeModal() {
    if (this.rootEl) {
      this.rerendered = false;
      this.props.onClose();
    }
  }

  getInnerContainerHeightInfo() {
    // We have to search the DOM for this since we went outside of React
    // for the render.
    let innerContainer = document.getElementById('modal-inner-container');
    if (!innerContainer) {
      return null;
    }

    let originalHeight = innerContainer.offsetHeight;

    // Height without padding, margin, border.
    let innerHeight = Util.getComputedDimensions(innerContainer).height;

    // Height of padding, margin, border.
    let outerHeight = originalHeight - innerHeight;

    // Modal cannot be bigger than this height.
    let maxHeight = window.innerHeight * this.props.maxHeightPercentage;

    return {
      // Add 10 for the gemini horizontal scrollbar
      maxHeight: Math.min(originalHeight, maxHeight + 10),

      // We minus the maxHeight with the outerHeight because it will
      // not show the content correctly due to 'box-sizing: border-box'.
      innerHeight: Math.min(innerHeight, maxHeight - outerHeight)
    };
  }

  getCloseButton() {
    if (!this.props.showCloseButton) {
      return null;
    }

    return (

          Close

    );
  }

  getFooter() {
    if (this.props.showFooter === false) {
      return null;
    }

    return (

          {this.props.footer}

    );
  }

  getModalContent(useScrollbar, innerHeight) {
    if (!useScrollbar && !this.rerendered) {
      return (

          {this.props.children}

      );
    }

    let geminiContainerStyle = {
      height: innerHeight
    };

    return (
      <GeminiScrollbar autoshow={true} className="container-scrollable" style={geminiContainerStyle}>

          {this.props.children}

      </GeminiScrollbar>
    );
  }

  getModal() {
    if (!this.props.open) {
      return null;
    }

    let backdropClassSet = classNames({
      'fade': true,
      'in': this.props.open,
      'modal-backdrop': true
    });

    let modalClassSet = classNames({
      'modal': true,
      'modal-large': true
    });

    let titleClassSet = classNames({
      'modal-header-title': true,
      'text-align-center': true,
      'flush-top': true,
      'flush-bottom': !this.props.subHeader,
      'inverse': true
    });

    let heightInfo = this.getInnerContainerHeightInfo();
    let maxHeight = null;
    let innerHeight = null;
    let useScrollbar = false;

    if (heightInfo !== null) {
      useScrollbar = true;
      innerHeight = heightInfo.innerHeight;
      maxHeight = heightInfo.maxHeight;
    }

    let modalStyle = {
      height: maxHeight
    };

    let containerStyle = {
      height: window.innerHeight
    };

    return (

          {this.getCloseButton()}

                {this.props.titleText}

              {this.props.subHeader}

              {this.getModalContent(useScrollbar, innerHeight)}

          {this.getFooter()}

    );
  }

  renderModal() {
    let modal = (
      <CSSTransitionGroup transitionAppear={true} transitionName="modal" component="section">
        {this.getModal()}
      </CSSTransitionGroup>
    );

    if (!this.rootEl) {
      this.rootEl = document.createElement('div');
      document.body.appendChild(this.rootEl);
    }

    React.render(
      modal,
      this.rootEl,
      // We need to rerender after the initial render
      // in order to have the children transition correctly.
      function () {
        if (!this.rerendered && this.props.open) {
          this.rerendered = true;
          this.renderModal();
        }
      }.bind(this)
    );
  }

  render() {
    return null;
  }

}

Modal.defaultProps = {
  // Default classes for each of the sections in the Modal.
  // This basically defaults to canvas UI classes.
  bodyClass: 'modal-content container-scrollable',
  closeButtonClass: 'modal-close',
  closeIconClass: 'modal-close-icon icon icon-mini icon-mini-white icon-close',
  closeTitleClass: 'modal-close-title',
  containerClass: 'modal-container',
  footerClass: 'modal-footer',
  footerContainerClass: 'container container-pod container-pod-short',
  headerClass: 'modal-header',
  headerContainerClass: 'container container-pod container-pod-short',
  innerBodyClass: 'modal-content-inner container container-pod container-pod-short',

  closeByBackdropClick: true,
  footer: null,
  maxHeightPercentage: 0.5,
  onClose: () => {},
  open: false,
  showCloseButton: false,
  showFooter: false,
  subHeader: '',
  titleText: ''
};

Modal.propTypes = {
  closeByBackdropClick: React.PropTypes.bool,
  footer: React.PropTypes.object,
  maxHeightPercentage: React.PropTypes.number,
  onClose: React.PropTypes.func,
  open: React.PropTypes.bool,
  showCloseButton: React.PropTypes.bool,
  showFooter: React.PropTypes.bool,
  subHeader: React.PropTypes.node,
  titleText: React.PropTypes.string,

  // Classes
  bodyClass: React.PropTypes.string,
  closeButtonClass: React.PropTypes.string,
  closeIconClass: React.PropTypes.string,
  closeTitleClass: React.PropTypes.string,
  containerClass: React.PropTypes.string,
  footerClass: React.PropTypes.string,
  footerContainerClass: React.PropTypes.string,
  headerClass: React.PropTypes.string,
  headerContainerClass: React.PropTypes.string,
  innerBodyClass: React.PropTypes.string
};
<commit_msg>Add comments to various renderModals<commit_after>import React from 'react/addons';
import classNames from 'classnames';
import GeminiScrollbar from 'react-gemini-scrollbar';

import * as Util from '../Util/Util';

const CSSTransitionGroup = React.addons.CSSTransitionGroup;
const METHODS_TO_BIND = ['handleWindowResize', 'handleBackdropClick', 'closeModal'];

export default class Modal extends React.Component {
  constructor() {
    super();

    METHODS_TO_BIND.forEach(function (method) {
      this[method] = this[method].bind(this);
    }, this);
  }

  componentDidUpdate() {
    // We need this in order to listen to the `open` prop change,
    // then we'll render the modal according to whether it's true
    // or false.
    this.renderModal();
  }

  componentDidMount() {
    // For initial mount, we need to call this to have the CSSTransitionGroup
    // on the page. There will be nothing inside of it because the modal will
    // be closed.
    this.renderModal();

    window.addEventListener('resize', this.handleWindowResize);
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleWindowResize);
  }

  shouldComponentUpdate(nextProps) {
    return nextProps.open !== this.props.open;
  }

  handleBackdropClick() {
    if (this.props.closeByBackdropClick) {
      this.closeModal();
    }
  }

  handleWindowResize() {
    this.renderModal();
  }

  closeModal() {
    if (this.rootEl) {
      this.rerendered = false;
      this.props.onClose();
    }
  }

  getInnerContainerHeightInfo() {
    // We have to search the DOM for this since we went outside of React
    // for the render.
    let innerContainer = document.getElementById('modal-inner-container');
    if (!innerContainer) {
      return null;
    }

    let originalHeight = innerContainer.offsetHeight;

    // Height without padding, margin, border.
    let innerHeight = Util.getComputedDimensions(innerContainer).height;

    // Height of padding, margin, border.
    let outerHeight = originalHeight - innerHeight;

    // Modal cannot be bigger than this height.
    let maxHeight = window.innerHeight * this.props.maxHeightPercentage;

    return {
      // Add 10 for the gemini horizontal scrollbar
      maxHeight: Math.min(originalHeight, maxHeight + 10),

      // We minus the maxHeight with the outerHeight because it will
      // not show the content correctly due to 'box-sizing: border-box'.
      innerHeight: Math.min(innerHeight, maxHeight - outerHeight)
    };
  }

  getCloseButton() {
    if (!this.props.showCloseButton) {
      return null;
    }

    return (

          Close

    );
  }

  getFooter() {
    if (this.props.showFooter === false) {
      return null;
    }

    return (

          {this.props.footer}

    );
  }

  getModalContent(useScrollbar, innerHeight) {
    if (!useScrollbar && !this.rerendered) {
      return (

          {this.props.children}

      );
    }

    let geminiContainerStyle = {
      height: innerHeight
    };

    return (
      <GeminiScrollbar autoshow={true} className="container-scrollable" style={geminiContainerStyle}>

          {this.props.children}

      </GeminiScrollbar>
    );
  }

  getModal() {
    if (!this.props.open) {
      return null;
    }

    let backdropClassSet = classNames({
      'fade': true,
      'in': this.props.open,
      'modal-backdrop': true
    });

    let modalClassSet = classNames({
      'modal': true,
      'modal-large': true
    });

    let titleClassSet = classNames({
      'modal-header-title': true,
      'text-align-center': true,
      'flush-top': true,
      'flush-bottom': !this.props.subHeader,
      'inverse': true
    });

    let heightInfo = this.getInnerContainerHeightInfo();
    let maxHeight = null;
    let innerHeight = null;
    let useScrollbar = false;

    if (heightInfo !== null) {
      useScrollbar = true;
      innerHeight = heightInfo.innerHeight;
      maxHeight = heightInfo.maxHeight;
    }

    let modalStyle = {
      height: maxHeight
    };

    let containerStyle = {
      height: window.innerHeight
    };

    return (

          {this.getCloseButton()}

                {this.props.titleText}

              {this.props.subHeader}

              {this.getModalContent(useScrollbar, innerHeight)}

          {this.getFooter()}

    );
  }

  renderModal() {
    let modal = (
      <CSSTransitionGroup transitionAppear={true} transitionName="modal" component="section">
        {this.getModal()}
      </CSSTransitionGroup>
    );

    if (!this.rootEl) {
      this.rootEl = document.createElement('div');
      document.body.appendChild(this.rootEl);
    }

    React.render(
      modal,
      this.rootEl,
      // We render once to compute the content height,
      // then render again to have access to the content height.
      function () {
        if (!this.rerendered && this.props.open) {
          this.rerendered = true;
          this.renderModal();
        }
      }.bind(this)
    );
  }

  render() {
    return null;
  }

}

Modal.defaultProps = {
  // Default classes for each of the sections in the Modal.
  // This basically defaults to canvas UI classes.
  bodyClass: 'modal-content container-scrollable',
  closeButtonClass: 'modal-close',
  closeIconClass: 'modal-close-icon icon icon-mini icon-mini-white icon-close',
  closeTitleClass: 'modal-close-title',
  containerClass: 'modal-container',
  footerClass: 'modal-footer',
  footerContainerClass: 'container container-pod container-pod-short',
  headerClass: 'modal-header',
  headerContainerClass: 'container container-pod container-pod-short',
  innerBodyClass: 'modal-content-inner container container-pod container-pod-short',

  closeByBackdropClick: true,
  footer: null,
  maxHeightPercentage: 0.5,
  onClose: () => {},
  open: false,
  showCloseButton: false,
  showFooter: false,
  subHeader: '',
  titleText: ''
};

Modal.propTypes = {
  closeByBackdropClick: React.PropTypes.bool,
  footer: React.PropTypes.object,
  maxHeightPercentage: React.PropTypes.number,
  onClose: React.PropTypes.func,
  open: React.PropTypes.bool,
  showCloseButton: React.PropTypes.bool,
  showFooter: React.PropTypes.bool,
  subHeader: React.PropTypes.node,
  titleText: React.PropTypes.string,

  // Classes
  bodyClass: React.PropTypes.string,
  closeButtonClass: React.PropTypes.string,
  closeIconClass: React.PropTypes.string,
  closeTitleClass: React.PropTypes.string,
  containerClass: React.PropTypes.string,
  footerClass: React.PropTypes.string,
  footerContainerClass: React.PropTypes.string,
  headerClass: React.PropTypes.string,
  headerContainerClass: React.PropTypes.string,
  innerBodyClass: React.PropTypes.string
};
<|endoftext|>


<commit_before>'use strict'

var hrs = ['6:00AM','7:00AM','8:00AM','9:00AM','10:00AM','11:00AM','12:00PM','1:00PM','2:00PM','3:00PM','4:00PM','5:00PM','6:00','7:00PM','8:00PM']

var pike = {
  minCust: 14,
  maxCust: 35,
  avgCup: 1.2,
  avgLb: 0.34,
  avgHrCust: [],

  custCount: function(min, max) {
    for (var i = 0; i < hrs.length; i++) {
    	this.avgHrCust.push(Math.floor(Math.random() * (max - min) + min));
    }
  },
  empNeed: function(cups) {
    return Math.floor(pike.custCount / cups + 1 )
  }
}

pike.custCount(pike.minCust, pike.maxCust);
pike.empNeed(pike.avgCup);
<commit_msg>creating more objects<commit_after>'use strict'

var hrs = ['6:00AM','7:00AM','8:00AM','9:00AM','10:00AM','11:00AM','12:00PM','1:00PM','2:00PM','3:00PM','4:00PM','5:00PM','6:00','7:00PM','8:00PM']

var pike = {
  location: 'Pike Place Market',
  minCust: 14,
  maxCust: 35,
  avgCup: 1.2,
  avgPounds: 0.34,
  custPerHour: [],
  custPerDay: 0,var round = function(num, prec){
   return parseFloat(num.toFixed(prec));
  };  cupsPerHour: [],
  cupsPerDay:0,
  poundsPerHr:[],
  poundsPerDay:0,
  empPerHr: [],
  empPerDay:0,

getRando: function(min,max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
},
getCust: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.custPerHour.push(this.getRando(this.minCust, this.maxCust));
    this.custPerDay += this.custPerHour[i];
  }
},
getCups: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.cupsPerHour.push(this.custPerHour[i] * this.avgCups);
    this.cupsPerDay += this.cupsPerHour[i];
  }
},
getPounds: function() {
  for (var i =0;i < hrs.length; i++) {
    this.poundsPerHr.push(this.custPerHour[i] * this.avgPounds);
    this.poundsPerDay += this.poundsPerHr[i];
  }
},
getEmp: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.empPerHr.push(Math.ceil(this.custPerHour[i] / 30));
    this.empPerDay += this.empPerHr[i];
     }
   }
}
pike.getCust();
pike.getCups();
pike.getPounds();
pike.getEmp();

var capHill = {
  location: 'Pike Place Market',
  minCust: 12,
  maxCust: 28,
  avgCup: 3.2,
  avgPounds: 0.03,
  custPerHour: [],
  custPerDay: 0,var round = function(num, prec){
   return parseFloat(num.toFixed(prec));
  };  cupsPerHour: [],
  cupsPerDay:0,
  poundsPerHr:[],
  poundsPerDay:0,
  empPerHr: [],
  empPerDay:0,

getRando: function(min,max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
},
getCust: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.custPerHour.push(this.getRando(this.minCust, this.maxCust));
    this.custPerDay += this.custPerHour[i];
  }
},
getCups: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.cupsPerHour.push(this.custPerHour[i] * this.avgCups);
    this.cupsPerDay += this.cupsPerHour[i];
  }
},
getPounds: function() {
  for (var i =0;i < hrs.length; i++) {
    this.poundsPerHr.push(this.custPerHour[i] * this.avgPounds);
    this.poundsPerDay += this.poundsPerHr[i];
  }
},
getEmp: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.empPerHr.push(Math.ceil(this.custPerHour[i] / 30));
    this.empPerDay += this.empPerHr[i];
     }
   }
}
capHill.getCust();
capHill.getCups();
capHill.getPounds();
capHill.getEmp();

var seaPubLib = {
  location: 'Pike Place Market',
  minCust: 9,
  maxCust: 45,
  avgCup: 2.6,
  avgPounds: 0.02,
  custPerHour: [],
  custPerDay: 0,var round = function(num, prec){
   return parseFloat(num.toFixed(prec));
  };  cupsPerHour: [],
  cupsPerDay:0,
  poundsPerHr:[],
  poundsPerDay:0,
  empPerHr: [],
  empPerDay:0,

getRando: function(min,max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
},
getCust: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.custPerHour.push(this.getRando(this.minCust, this.maxCust));
    this.custPerDay += this.custPerHour[i];
  }
},
getCups: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.cupsPerHour.push(this.custPerHour[i] * this.avgCups);
    this.cupsPerDay += this.cupsPerHour[i];
  }
},
getPounds: function() {
  for (var i =0;i < hrs.length; i++) {
    this.poundsPerHr.push(this.custPerHour[i] * this.avgPounds);
    this.poundsPerDay += this.poundsPerHr[i];
  }
},
getEmp: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.empPerHr.push(Math.ceil(this.custPerHour[i] / 30));
    this.empPerDay += this.empPerHr[i];
     }
   }
}
seaPubLib.getCust();
seaPubLib.getCups();
seaPubLib.getPounds();
seaPubLib.getEmp();

var southLakeUnion = {
  location: 'Pike Place Market',
  minCust: 5,
  maxCust: 18,
  avgCup: 1.3,
  avgPounds: 0.04,
  custPerHour: [],
  custPerDay: 0,var round = function(num, prec){
   return parseFloat(num.toFixed(prec));
  };  cupsPerHour: [],
  cupsPerDay:0,
  poundsPerHr:[],
  poundsPerDay:0,
  empPerHr: [],
  empPerDay:0,

getRando: function(min,max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
},
getCust: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.custPerHour.push(this.getRando(this.minCust, this.maxCust));
    this.custPerDay += this.custPerHour[i];
  }
},
getCups: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.cupsPerHour.push(this.custPerHour[i] * this.avgCups);
    this.cupsPerDay += this.cupsPerHour[i];
  }
},
getPounds: function() {
  for (var i =0;i < hrs.length; i++) {
    this.poundsPerHr.push(this.custPerHour[i] * this.avgPounds);
    this.poundsPerDay += this.poundsPerHr[i];
  }
},
getEmp: function() {
  for (var i = 0; i < hrs.length; i++) {
    this.empPerHr.push(Math.ceil(this.custPerHour[i] / 30));
    this.empPerDay += this.empPerHr[i];
     }
   }
}
southLakeUnion.getCust();
southLakeUnion.getCups();
southLakeUnion.getPounds();
southLakeUnion.getEmp();
<|endoftext|>