<commit_before>/**
 * Player Object
 */
const Player = {

    YTPlayer: undefined,
    update: undefined,

    GUI: {
        title: document.getElementById("title"),
        time: document.getElementById("time"),
        duration: document.getElementById("duration"),
        controls: {
            play: document.getElementById("play")
        },
        searchField: document.getElementById("search")
    },

    /**
     * Gets fired when the YT Player is Loaded
     */
    onReady: function(event) {
        console.log("PLAYER IS LOADED");
        let player = event.target;
        Player.GUI.title.innerText = player.getVideoData().title;

        //Display time
        let duration = Player.formatTime(player.getDuration());
        Player.GUI.duration.innerText = duration;
        Player.GUI.time.innerText = "00:00";

        //Add event listeners for the GUI
        Player.GUI.controls.play.addEventListener("click", Player.changeVideoState);

        //Initialise updateTime function
        Player.update = setInterval(Player.updateTime, 1000);

        //Start the video
        Player.play();
    },

    /**
     * Gets called when the state of the player gets changed
     */
    onStateChange: function(event) {
        const player = event.target;
        console.log("State changed to: ", player.getPlayerState());
    },

    /**
     * Switches between playing and pausing
     */
    changeVideoState: function() {
        if(Player.YTPlayer.getPlayerState() == YT.PlayerState.PLAYING) {
            clearInterval(Player.update);
            Player.pause();
        } else {
            Player.update = setInterval(Player.updateTime, 1000);
            Player.play();
        }
    },

    /**
     * Formats the seconds in the style mm:ss
     * @param {number} seconds
     * @return {string} The formatted time as string
     */
    formatTime: function(seconds) {
        seconds = Math.round(seconds);
        let minutes = Math.floor(seconds / 60);
        seconds = seconds - minutes * 60;
        let time = Player.str_pad_left(minutes, "0", 2) + ':' + Player.str_pad_left(seconds, "0", 2);
        return time;
    },

    /**
     * This function is used to update the time correctly
     * @return {[type]} [description]
     */
    updateTime: function() {
        console.log("Updating Time");
        let currentTime = Player.formatTime(Player.YTPlayer.getCurrentTime());
        Player.GUI.time.innerText = currentTime;
    },

    /**
     * Start/continue playback of video
     */
    play: function() {
        $("#play .icon").removeClass("fa-play");
        $("#play .icon").addClass("fa-pause");
        Player.YTPlayer.playVideo();
    },

    /**
     * Pause the playback of the video
     */
    pause: function() {
        $("#play .icon").removeClass("fa-pause");
        $("#play .icon").addClass("fa-play");
        Player.YTPlayer.pauseVideo();
    },

    loadVideoById: function(id) {
        Player.YTPlayer.loadVideoByid(id);
    },

    /**
     * Used the pad the time correctly
     */
    str_pad_left: function(string,pad,length) {
        return (new Array(length+1).join(pad)+string).slice(-length);
    },

    loadVideo: function() {
        console.log("LOADING VIDEO");
        Player.clearPlayer();
        Player.YTPlayer = new YT.Player('player', {
            height: 1,
            width: 1,
            videoId: Player.GUI.searchField.value,
            events: {
                'onReady': Player.onReady,
                'onStateChange': Player.onStateChange
            }
        });
        console.log("object created");
    },

    clearPlayer: function() {
        console.log("CLEARING VIDEO");
        if(Player.YTPlayer !== undefined && Player.YTPlayer !== null) {
            Player.YTPlayer.stopVideo();
            Player.YTPlayer.clearVideo();
            Player.YTPlayer.destroy();
        }

        //Remove Event Listener
        Player.GUI.controls.play.removeEventListener("click", Player.changeVideoState);

        //Clear intervals and the YT.Player object
        clearInterval(Player.update);
        Player.update = undefined;
        Player.YTPlayer = undefined;
    }
};<commit_msg>Removed more old jquery code<commit_after>/**
 * Player Object
 */
const Player = {

    YTPlayer: undefined,
    update: undefined,

    GUI: {
        title: document.getElementById("title"),
        time: document.getElementById("time"),
        duration: document.getElementById("duration"),
        controls: {
            play: document.getElementById("play")
        },
        searchField: document.getElementById("search")
    },

    /**
     * Gets fired when the YT Player is Loaded
     */
    onReady: function(event) {
        console.log("PLAYER IS LOADED");
        let player = event.target;
        Player.GUI.title.innerText = player.getVideoData().title;

        //Display time
        let duration = Player.formatTime(player.getDuration());
        Player.GUI.duration.innerText = duration;
        Player.GUI.time.innerText = "00:00";

        //Add event listeners for the GUI
        Player.GUI.controls.play.addEventListener("click", Player.changeVideoState);

        //Initialise updateTime function
        Player.update = setInterval(Player.updateTime, 1000);

        //Start the video
        Player.play();
    },

    /**
     * Gets called when the state of the player gets changed
     */
    onStateChange: function(event) {
        const player = event.target;
        console.log("State changed to: ", player.getPlayerState());
    },

    /**
     * Switches between playing and pausing
     */
    changeVideoState: function() {
        if(Player.YTPlayer.getPlayerState() == YT.PlayerState.PLAYING) {
            clearInterval(Player.update);
            Player.pause();
        } else {
            Player.update = setInterval(Player.updateTime, 1000);
            Player.play();
        }
    },

    /**
     * Formats the seconds in the style mm:ss
     * @param {number} seconds
     * @return {string} The formatted time as string
     */
    formatTime: function(seconds) {
        seconds = Math.round(seconds);
        let minutes = Math.floor(seconds / 60);
        seconds = seconds - minutes * 60;
        let time = Player.str_pad_left(minutes, "0", 2) + ':' + Player.str_pad_left(seconds, "0", 2);
        return time;
    },

    /**
     * This function is used to update the time correctly
     * @return {[type]} [description]
     */
    updateTime: function() {
        console.log("Updating Time");
        let currentTime = Player.formatTime(Player.YTPlayer.getCurrentTime());
        Player.GUI.time.innerText = currentTime;
    },

    /**
     * Start/continue playback of video
     */
    play: function() {
        $("#play .icon").removeClass("fa-play");
        $("#play .icon").addClass("fa-pause");
        Player.YTPlayer.playVideo();
    },

    /**
     * Pause the playback of the video
     */
    pause: function() {
        $("#play .icon").removeClass("fa-pause");
        $("#play .icon").addClass("fa-play");
        Player.YTPlayer.pauseVideo();
    },

    loadVideoById: function(id) {
        Player.YTPlayer.loadVideoByid(id);
    },

    /**
     * Used the pad the time correctly
     */
    str_pad_left: function(string,pad,length) {
        return (new Array(length+1).join(pad)+string).slice(-length);
    },

    loadVideo: function() {
        console.log("LOADING VIDEO");
        Player.clearPlayer();
        Player.YTPlayer = new YT.Player('player', {
            height: 1,
            width: 1,
            //videoId: Player.GUI.searchField.value,
            events: {
                'onReady': Player.onReady,
                'onStateChange': Player.onStateChange
            }
        });
        console.log("object created");
    },

    clearPlayer: function() {
        console.log("CLEARING VIDEO");
        if(Player.YTPlayer !== undefined && Player.YTPlayer !== null) {
            Player.YTPlayer.stopVideo();
            Player.YTPlayer.clearVideo();
            Player.YTPlayer.destroy();
        }

        //Remove Event Listener
        Player.GUI.controls.play.removeEventListener("click", Player.changeVideoState);

        //Clear intervals and the YT.Player object
        clearInterval(Player.update);
        Player.update = undefined;
        Player.YTPlayer = undefined;
    }
};<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React, { PureComponent } from 'react'
import TextField from '@material-ui/core/TextField'

export default class UserWords extends PureComponent {
	static propTypes = {
		onChange: PropTypes.func.isRequired,
		value: PropTypes.string.isRequired,
		onKeyDown: PropTypes.func.isRequired
	}

	render() {
		const { onChange, value, onKeyDown } = this.props

		return (
			<TextField
				label="Type the word, you want to learn"
				placeholder="example"
				helperText="You can enter several words at once. Type one word per line using 'Shift + Enter' to add new lines"
				variant="outlined"
				fullWidth
				multiline
				rowsMax={20}
				value={value}
				onChange={onChange}
				onKeyDown={onKeyDown}
			/>
		)
	}
}
<commit_msg>fix: wording<commit_after>import PropTypes from 'prop-types'
import React, { PureComponent } from 'react'
import TextField from '@material-ui/core/TextField'

export default class UserWords extends PureComponent {
	static propTypes = {
		onChange: PropTypes.func.isRequired,
		value: PropTypes.string.isRequired,
		onKeyDown: PropTypes.func.isRequired
	}

	render() {
		const { onChange, value, onKeyDown } = this.props

		return (
			<TextField
				label="Type the word, you want to learn"
				placeholder="example"
				helperText="You can enter several words. Type one word per line using 'Shift + Enter' to add new lines"
				variant="outlined"
				fullWidth
				multiline
				rowsMax={20}
				value={value}
				onChange={onChange}
				onKeyDown={onKeyDown}
			/>
		)
	}
}
<|endoftext|>


<commit_before>describe('sooper', function() {

	it('exists', function() {
		expect(sooper).toBeDefined();
	});

	it('has correct properties', function() {
		expect(Object.getOwnPropertyNames(sooper).length).toBe(2);
		expect(sooper.hasOwnProperty('define')).toBe(true);
		expect(sooper.hasOwnProperty('version')).toBe(true);
		expect(sooper.version).toBe("2.0.0");
	});

	describe('defining a class', function() {
		describe('with nothing', function() {
			it('can be defined', function() {
				function createClassWithoutConstructor() {
					sooper.define('TestClass', {});
				}
				expect(createClassWithoutConstructor).not.toThrow();
				expect(TestClass).toBeDefined();
				expect(TestClass instanceof Function).toBe(true);
				expect(TestClass.prototype.constructor).not.toBe(Object);
			});

			it('can be instantiated', function() {
				var test = new TestClass();
				expect(test instanceof Object).toBe(true);
				expect(test instanceof TestClass).toBe(true);
				expect(Object.getOwnPropertyNames(test).length).toBe(0);
				expect(Object.keys(test).length).toBe(0);

				delete TestClass;
			});

			it('creates unique constructors', function() {
				sooper.define('TestClass1', {
					value: 1
				});
				sooper.define('TestClass2', {
					value: 2
				});
				var t1 = new TestClass1(),
					t2 = new TestClass2();
				expect(TestClass1.prototype.constructor).not.toBe(TestClass2.prototype.constructor);
				expect(t1.value).toBe(1);
				expect(t2.value).toBe(2);

				delete TestClass1;
				delete TestClass2;
			});
		});
		describe('with only a constructor', function() {
			it('can be defined', function() {
				function createClassWithConstructor() {
					sooper.define('TestClass', {
						constructor: function(){
							this.value = 42;
						}
					});
				}
				expect(createClassWithConstructor).not.toThrow();
				expect(TestClass).toBeDefined();
			});

			it('can be instantiated', function() {
				var test = new TestClass();
				expect(Object.getOwnPropertyNames(test).length).toBe(1);
				expect(Object.keys(test).length).toBe(1);
				expect(test.value).toBe(42);

				delete TestClass;
			});
		});

		describe('with members', function() {
			function accessorGetter() { return 'accessor' };
			function accessorSetter() {};

			it('can be defined', function() {
				var testClassConfig = {
					constructor: function(value) {
						this.memberVar = value;
					},
					memberVar: 42,
					memberFunc: function() {
						return this.memberVar;
					}
				};
				Object.defineProperty(testClassConfig, 'data', {
					enumerable: false,
					configurable: false,
					writable: false,
					value: 'data'
				});
				Object.defineProperty(testClassConfig, 'accessor', {
					enumerable: false,
					configurable: false,
					get: accessorGetter,
					set: accessorSetter
				});
				sooper.define('TestClass', testClassConfig);

				expect(TestClass).toBeDefined();
			});

			it('has correct properties', function() {
				var proto = TestClass.prototype;
				expect(proto.memberVar).toBe(42);
				expect(proto.memberFunc instanceof Function).toBe(true);
				expect(proto.data).toBe('data');
				expect(proto.accessor).toBe('accessor');
				expect(proto.hasOwnProperty('memberVar')).toBe(true);
				expect(proto.hasOwnProperty('memberFunc')).toBe(true);
				expect(proto.hasOwnProperty('data')).toBe(true);
				expect(proto.hasOwnProperty('accessor')).toBe(true);
			});

			it('retains property descriptors', function() {
				var proto = TestClass.prototype;
				expect(Object.getOwnPropertyDescriptor(proto,'memberVar')).toEqual(jasmine.objectContaining({
					writable: true,
					enumerable: true,
					configurable: true
				}));
				expect(Object.getOwnPropertyDescriptor(proto,'memberFunc')).toEqual(jasmine.objectContaining({
					writable: true,
					enumerable: true,
					configurable: true
				}));
				expect(Object.getOwnPropertyDescriptor(proto,'data')).toEqual(jasmine.objectContaining({
					enumerable: false,
					configurable: false,
					writable: false
				}));
				expect(Object.getOwnPropertyDescriptor(proto,'accessor')).toEqual(jasmine.objectContaining({
					enumerable: false,
					configurable: false,
					get: accessorGetter,
					set: accessorSetter
				}));
			});

			it('can be instantiated', function() {
				var test = new TestClass(21);
				expect(Object.getOwnPropertyNames(test)).toEqual(['memberVar']);
				expect(Object.keys(test)).toEqual(['memberVar']);
				expect(test.memberVar).toBe(21);
				expect(test.memberFunc()).toBe(21);

				delete TestClass;
			});
		});

		describe('with a namespace', function() {
			describe('single level', function(){
				it('is created', function() {
					sooper.define('namespace.TestClass1', {
						constructor: function() {
							this.test = true;
						}
					});
					sooper.define('namespace.TestClass2', {
						constructor: function() {
							this.test = true;
						}
					});

					expect(namespace).toBeDefined();
					expect(namespace.TestClass1).toBeDefined();
					expect(namespace.TestClass2).toBeDefined();
					expect((new namespace.TestClass1).test).toBe(true);
					expect((new namespace.TestClass2).test).toBe(true);

					delete namespace;
				});
			});

			describe('multiple levels', function() {
				it('is created', function() {
					sooper.define('namespace1.namespace2.TestClass', {
						constructor: function() {
							this.test = true;
						}
					});

					expect(namespace1).toBeDefined();
					expect(namespace1.namespace2).toBeDefined();
					expect(namespace1.namespace2.TestClass).toBeDefined();
					expect((new namespace1.namespace2.TestClass).test).toBe(true);

					delete namespace1;
				});
			});
		});

		describe('without a namespace', function() {
			function createWithoutNamespace () {
				return sooper.define({
					constructor: function() {},
					value: 42
				});
			}
			it('does not throw an error', function() {
				expect(createWithoutNamespace).not.toThrow();
			});
			it('returns the class', function() {
				var TestClass = createWithoutNamespace();
				expect(TestClass).toBeDefined();
				expect(TestClass instanceof Function).toBe(true);
			});
			it('can be instantiated', function() {
				var t = new (createWithoutNamespace())();
				expect(t.value).toBe(42);
			});
		});
	});

	describe('inheriting a class (basic)', function() {
		it('can inherit', function() {
			sooper.define('SuperClass', {
				superVar: 42,
				constructor: function(value) {
					if(arguments.length)
						this.superVar = value;
				},
				superFunc: function() { return this.superVar; },
				commonFunc: function() { return 1; }
			});
			sooper.define('TestClass', {
				inherits: SuperClass,
				subVar: 21,
				constructor: function(value) {
					SuperClass.apply(this,arguments);
					if (arguments.length)
						this.subVar = value + 1;
				},
				subFunc: function() { return this.subVar; },
				commonFunc: function() { return 2; }
			});
			expect(TestClass.prototype.constructor).toBe(SuperClass);
		});

		it('can instantiate without args', function() {
			var test = new TestClass();
			expect(test instanceof TestClass);
			expect(test instanceof SuperClass);
			expect(test.subVar).toBe(21);
			expect(test.subFunc()).toBe(21);
			expect(test.superVar).toBe(42);
			expect(test.superFunc()).toBe(42);
		});

		it('can instantiate with args', function() {
			var test = new TestClass(1);
			expect(test.subVar).toBe(2);
			expect(test.subFunc()).toBe(2);
			expect(test.superVar).toBe(1);
			expect(test.superFunc()).toBe(1);
		});

		it('overrides super class properties', function() {
			var test = new TestClass();
			expect(test.commonFunc()).toBe(2);

			delete TestClass;
			delete SuperClass;
		});
	});

	describe('inheriting a class (advanced)', function() {
		afterEach(function() {
			delete TestClass;
			delete SuperClass;
		});

		it('can call super constructor', function() {
			sooper.define('SuperClass', {
				constructor: function(value) {
					this.testVar1 = value;
				}
			});
			sooper.define('TestClass', {
				inherits: SuperClass,
				constructor: function(value) {
					this.super(value);
					this.testVar2 = value*2;
				}
			});
			var test = new TestClass(42);
			expect(test.testVar1).toBe(42);
			expect(test.testVar2).toBe(84);
		});

		it('can call super function on super class', function() {
			sooper.define('SuperClass', {
				testVar: 1,
				constructor: function() {},
				testFunc: function(value) {
					return this.testVar+value;
				}
			});
			sooper.define('TestClass', {
				inherits: SuperClass,
				constructor: function() {},
				testFunc: function me(value) {
					return me.super.call(this,value) + 1;
				}
			});
			var test = new TestClass();
			expect(test.testFunc(1)).toBe(3);
		});
	});

	describe('implementing interfaces (basic)', function() {
		it('can implement a single interface', function() {
			sooper.define('TestInterface', {
				constructor:function(){},
				interfaceVar: 42,
				interfaceFunc: function(){}
			});
			sooper.define('TestClass', {
				implements: TestInterface,
				constructor: function() {}
			});
			expect(TestClass.prototype.interfaceVar).toBe(42);
			expect(TestClass.prototype.interfaceFunc).toBe(TestInterface.prototype.interfaceFunc);
			delete TestClass;
		});

		it('can implement multiple interfaces', function() {
			sooper.define('TestInterface2', {
				constructor:function(){},
				interface2Var: 21,
				interface2Func: function(){}
			});
			sooper.define('TestClass', {
				implements: [TestInterface,TestInterface2],
				constructor: function() {}
			});
			expect(TestClass.prototype.interfaceVar).toBe(42);
			expect(TestClass.prototype.interfaceFunc).toBe(TestInterface.prototype.interfaceFunc);
			expect(TestClass.prototype.interface2Var).toBe(21);
			expect(TestClass.prototype.interface2Func).toBe(TestInterface2.prototype.interface2Func);
		});

		it('can be instantiated', function() {
			var test = new TestClass();
			expect(test.interfaceVar).toBe(42);
			expect(test.interfaceFunc).toBe(TestInterface.prototype.interfaceFunc);
			expect(test.interface2Var).toBe(21);
			expect(test.interface2Func).toBe(TestInterface2.prototype.interface2Func);

			delete TestClass;
			delete TestInterface2;
			delete TestInterface;
		});
	});

	describe('implementing interfaces (advanced)', function() {
		it('can implement an interface that implements an interface', function() {
			sooper.define('TestInterface1', {
				constructor:function(){},
				interface1Var: 1,
				interface1Func: function(){}
			});
			sooper.define('TestInterface2', {
				implements: TestInterface1,
				constructor:function(){},
				interface2Var: 2,
				interface2Func: function(){}
			});
			sooper.define('TestClass', {
				implements: TestInterface2,
				constructor: function() {}
			});
			expect(TestClass.prototype.interface1Var).toBe(1);
			expect(TestClass.prototype.interface1Func).toBe(TestInterface1.prototype.interface1Func);
			expect(TestClass.prototype.interface2Var).toBe(2);
			expect(TestClass.prototype.interface2Func).toBe(TestInterface2.prototype.interface2Func);
			delete TestClass;
			delete TestInterface2;
			delete TestInterface1;
		});

		it('later interfaces override earlier interfaces', function() {
			sooper.define('TestInterface1', {
				constructor:function(){},
				testVar: 1,
				testFunc: function(){ return 1; }
			});
			sooper.define('TestInterface2', {
				constructor:function(){},
				testVar: 2,
				testFunc: function(){ return 2; }
			});
			sooper.define('TestClass', {
				implements: [TestInterface1,TestInterface2],
				constructor: function() {}
			});
			expect(TestClass.prototype.testVar).toBe(2);
			expect(TestClass.prototype.testFunc).toBe(TestInterface2.prototype.testFunc);
			delete TestClass;
			delete TestInterface2;
			delete TestInterface1;
		});

		it('class properties override interface properties', function() {
			sooper.define('TestInterface', {
				constructor:function(){},
				testVar: 1,
				testFunc: function(){return 1;}
			});
			sooper.define('TestClass', {
				implements: TestInterface,
				testVar: 2,
				testFunc: function(){return 2;},
				constructor: function() {}
			});
			var test = new TestClass();
			expect(test.testVar).toBe(2);
			expect(test.testFunc()).toBe(2);
			delete TestClass;
			delete TestInterface;
		});

		it('can call overriden function on interface via super', function() {
			sooper.define('TestInterface', {
				testVar: 1,
				constructor: function() {},
				testFunc: function(value) {
					return this.testVar+value;
				}
			});
			sooper.define('TestClass', {
				implements: TestInterface,
				constructor: function() {},
				testFunc: function me(value) {
					return me.super.call(this,value) + 1;
				}
			});
			var test = new TestClass();
			expect(test.testFunc(1)).toBe(3);
		});
	});
});
<commit_msg>removed unnecessary constructors from tests<commit_after>describe('sooper', function() {

	it('exists', function() {
		expect(sooper).toBeDefined();
	});

	it('has correct properties', function() {
		expect(Object.getOwnPropertyNames(sooper).length).toBe(2);
		expect(sooper.hasOwnProperty('define')).toBe(true);
		expect(sooper.hasOwnProperty('version')).toBe(true);
		expect(sooper.version).toBe("2.0.0");
	});

	describe('defining a class', function() {
		describe('with nothing', function() {
			it('can be defined', function() {
				function createClassWithoutConstructor() {
					sooper.define('TestClass', {});
				}
				expect(createClassWithoutConstructor).not.toThrow();
				expect(TestClass).toBeDefined();
				expect(TestClass instanceof Function).toBe(true);
				expect(TestClass.prototype.constructor).not.toBe(Object);
			});

			it('can be instantiated', function() {
				var test = new TestClass();
				expect(test instanceof Object).toBe(true);
				expect(test instanceof TestClass).toBe(true);
				expect(Object.getOwnPropertyNames(test).length).toBe(0);
				expect(Object.keys(test).length).toBe(0);

				delete TestClass;
			});

			it('creates unique constructors', function() {
				sooper.define('TestClass1', {
					value: 1
				});
				sooper.define('TestClass2', {
					value: 2
				});
				var t1 = new TestClass1(),
					t2 = new TestClass2();
				expect(TestClass1.prototype.constructor).not.toBe(TestClass2.prototype.constructor);
				expect(t1.value).toBe(1);
				expect(t2.value).toBe(2);

				delete TestClass1;
				delete TestClass2;
			});
		});
		describe('with only a constructor', function() {
			it('can be defined', function() {
				function createClassWithConstructor() {
					sooper.define('TestClass', {
						constructor: function(){
							this.value = 42;
						}
					});
				}
				expect(createClassWithConstructor).not.toThrow();
				expect(TestClass).toBeDefined();
			});

			it('can be instantiated', function() {
				var test = new TestClass();
				expect(Object.getOwnPropertyNames(test).length).toBe(1);
				expect(Object.keys(test).length).toBe(1);
				expect(test.value).toBe(42);

				delete TestClass;
			});
		});

		describe('with members', function() {
			function accessorGetter() { return 'accessor' };
			function accessorSetter() {};

			it('can be defined', function() {
				var testClassConfig = {
					constructor: function(value) {
						this.memberVar = value;
					},
					memberVar: 42,
					memberFunc: function() {
						return this.memberVar;
					}
				};
				Object.defineProperty(testClassConfig, 'data', {
					enumerable: false,
					configurable: false,
					writable: false,
					value: 'data'
				});
				Object.defineProperty(testClassConfig, 'accessor', {
					enumerable: false,
					configurable: false,
					get: accessorGetter,
					set: accessorSetter
				});
				sooper.define('TestClass', testClassConfig);

				expect(TestClass).toBeDefined();
			});

			it('has correct properties', function() {
				var proto = TestClass.prototype;
				expect(proto.memberVar).toBe(42);
				expect(proto.memberFunc instanceof Function).toBe(true);
				expect(proto.data).toBe('data');
				expect(proto.accessor).toBe('accessor');
				expect(proto.hasOwnProperty('memberVar')).toBe(true);
				expect(proto.hasOwnProperty('memberFunc')).toBe(true);
				expect(proto.hasOwnProperty('data')).toBe(true);
				expect(proto.hasOwnProperty('accessor')).toBe(true);
			});

			it('retains property descriptors', function() {
				var proto = TestClass.prototype;
				expect(Object.getOwnPropertyDescriptor(proto,'memberVar')).toEqual(jasmine.objectContaining({
					writable: true,
					enumerable: true,
					configurable: true
				}));
				expect(Object.getOwnPropertyDescriptor(proto,'memberFunc')).toEqual(jasmine.objectContaining({
					writable: true,
					enumerable: true,
					configurable: true
				}));
				expect(Object.getOwnPropertyDescriptor(proto,'data')).toEqual(jasmine.objectContaining({
					enumerable: false,
					configurable: false,
					writable: false
				}));
				expect(Object.getOwnPropertyDescriptor(proto,'accessor')).toEqual(jasmine.objectContaining({
					enumerable: false,
					configurable: false,
					get: accessorGetter,
					set: accessorSetter
				}));
			});

			it('can be instantiated', function() {
				var test = new TestClass(21);
				expect(Object.getOwnPropertyNames(test)).toEqual(['memberVar']);
				expect(Object.keys(test)).toEqual(['memberVar']);
				expect(test.memberVar).toBe(21);
				expect(test.memberFunc()).toBe(21);

				delete TestClass;
			});
		});

		describe('with a namespace', function() {
			describe('single level', function(){
				it('is created', function() {
					sooper.define('namespace.TestClass1', {
						constructor: function() {
							this.test = true;
						}
					});
					sooper.define('namespace.TestClass2', {
						constructor: function() {
							this.test = true;
						}
					});

					expect(namespace).toBeDefined();
					expect(namespace.TestClass1).toBeDefined();
					expect(namespace.TestClass2).toBeDefined();
					expect((new namespace.TestClass1).test).toBe(true);
					expect((new namespace.TestClass2).test).toBe(true);

					delete namespace;
				});
			});

			describe('multiple levels', function() {
				it('is created', function() {
					sooper.define('namespace1.namespace2.TestClass', {
						constructor: function() {
							this.test = true;
						}
					});

					expect(namespace1).toBeDefined();
					expect(namespace1.namespace2).toBeDefined();
					expect(namespace1.namespace2.TestClass).toBeDefined();
					expect((new namespace1.namespace2.TestClass).test).toBe(true);

					delete namespace1;
				});
			});
		});

		describe('without a namespace', function() {
			function createWithoutNamespace () {
				return sooper.define({
					constructor: function() {},
					value: 42
				});
			}
			it('does not throw an error', function() {
				expect(createWithoutNamespace).not.toThrow();
			});
			it('returns the class', function() {
				var TestClass = createWithoutNamespace();
				expect(TestClass).toBeDefined();
				expect(TestClass instanceof Function).toBe(true);
			});
			it('can be instantiated', function() {
				var t = new (createWithoutNamespace())();
				expect(t.value).toBe(42);
			});
		});
	});

	describe('inheriting a class (basic)', function() {
		it('can inherit', function() {
			sooper.define('SuperClass', {
				superVar: 42,
				constructor: function(value) {
					if(arguments.length)
						this.superVar = value;
				},
				superFunc: function() { return this.superVar; },
				commonFunc: function() { return 1; }
			});
			sooper.define('TestClass', {
				inherits: SuperClass,
				subVar: 21,
				constructor: function(value) {
					SuperClass.apply(this,arguments);
					if (arguments.length)
						this.subVar = value + 1;
				},
				subFunc: function() { return this.subVar; },
				commonFunc: function() { return 2; }
			});
			expect(TestClass.prototype.constructor).toBe(SuperClass);
		});

		it('can instantiate without args', function() {
			var test = new TestClass();
			expect(test instanceof TestClass);
			expect(test instanceof SuperClass);
			expect(test.subVar).toBe(21);
			expect(test.subFunc()).toBe(21);
			expect(test.superVar).toBe(42);
			expect(test.superFunc()).toBe(42);
		});

		it('can instantiate with args', function() {
			var test = new TestClass(1);
			expect(test.subVar).toBe(2);
			expect(test.subFunc()).toBe(2);
			expect(test.superVar).toBe(1);
			expect(test.superFunc()).toBe(1);
		});

		it('overrides super class properties', function() {
			var test = new TestClass();
			expect(test.commonFunc()).toBe(2);

			delete TestClass;
			delete SuperClass;
		});
	});

	describe('inheriting a class (advanced)', function() {
		afterEach(function() {
			delete TestClass;
			delete SuperClass;
		});

		it('can call super constructor', function() {
			sooper.define('SuperClass', {
				constructor: function(value) {
					this.testVar1 = value;
				}
			});
			sooper.define('TestClass', {
				inherits: SuperClass,
				constructor: function(value) {
					this.super(value);
					this.testVar2 = value*2;
				}
			});
			var test = new TestClass(42);
			expect(test.testVar1).toBe(42);
			expect(test.testVar2).toBe(84);
		});

		it('can call super function on super class', function() {
			sooper.define('SuperClass', {
				testVar: 1,
				constructor: function() {},
				testFunc: function(value) {
					return this.testVar+value;
				}
			});
			sooper.define('TestClass', {
				inherits: SuperClass,
				constructor: function() {},
				testFunc: function me(value) {
					return me.super.call(this,value) + 1;
				}
			});
			var test = new TestClass();
			expect(test.testFunc(1)).toBe(3);
		});
	});

	describe('implementing interfaces (basic)', function() {
		it('can implement a single interface', function() {
			sooper.define('TestInterface', {
				interfaceVar: 42,
				interfaceFunc: function(){}
			});
			sooper.define('TestClass', {
				implements: TestInterface,
				constructor: function() {}
			});
			expect(TestClass.prototype.interfaceVar).toBe(42);
			expect(TestClass.prototype.interfaceFunc).toBe(TestInterface.prototype.interfaceFunc);
			delete TestClass;
		});

		it('can implement multiple interfaces', function() {
			sooper.define('TestInterface2', {
				interface2Var: 21,
				interface2Func: function(){}
			});
			sooper.define('TestClass', {
				implements: [TestInterface,TestInterface2]
			});
			expect(TestClass.prototype.interfaceVar).toBe(42);
			expect(TestClass.prototype.interfaceFunc).toBe(TestInterface.prototype.interfaceFunc);
			expect(TestClass.prototype.interface2Var).toBe(21);
			expect(TestClass.prototype.interface2Func).toBe(TestInterface2.prototype.interface2Func);
		});

		it('can be instantiated', function() {
			var test = new TestClass();
			expect(test.interfaceVar).toBe(42);
			expect(test.interfaceFunc).toBe(TestInterface.prototype.interfaceFunc);
			expect(test.interface2Var).toBe(21);
			expect(test.interface2Func).toBe(TestInterface2.prototype.interface2Func);

			delete TestClass;
			delete TestInterface2;
			delete TestInterface;
		});
	});

	describe('implementing interfaces (advanced)', function() {
		it('can implement an interface that implements an interface', function() {
			sooper.define('TestInterface1', {
				interface1Var: 1,
				interface1Func: function(){}
			});
			sooper.define('TestInterface2', {
				implements: TestInterface1,
				interface2Var: 2,
				interface2Func: function(){}
			});
			sooper.define('TestClass', {
				implements: TestInterface2
			});
			expect(TestClass.prototype.interface1Var).toBe(1);
			expect(TestClass.prototype.interface1Func).toBe(TestInterface1.prototype.interface1Func);
			expect(TestClass.prototype.interface2Var).toBe(2);
			expect(TestClass.prototype.interface2Func).toBe(TestInterface2.prototype.interface2Func);
			delete TestClass;
			delete TestInterface2;
			delete TestInterface1;
		});

		it('later interfaces override earlier interfaces', function() {
			sooper.define('TestInterface1', {
				testVar: 1,
				testFunc: function(){ return 1; }
			});
			sooper.define('TestInterface2', {
				testVar: 2,
				testFunc: function(){ return 2; }
			});
			sooper.define('TestClass', {
				implements: [TestInterface1,TestInterface2]
			});
			expect(TestClass.prototype.testVar).toBe(2);
			expect(TestClass.prototype.testFunc).toBe(TestInterface2.prototype.testFunc);
			delete TestClass;
			delete TestInterface2;
			delete TestInterface1;
		});

		it('class properties override interface properties', function() {
			sooper.define('TestInterface', {
				testVar: 1,
				testFunc: function(){return 1;}
			});
			sooper.define('TestClass', {
				implements: TestInterface,
				testVar: 2,
				testFunc: function(){return 2;}
			});
			var test = new TestClass();
			expect(test.testVar).toBe(2);
			expect(test.testFunc()).toBe(2);
			delete TestClass;
			delete TestInterface;
		});

		it('can call overriden function on interface via super', function() {
			sooper.define('TestInterface', {
				testVar: 1,
				testFunc: function(value) {
					return this.testVar+value;
				}
			});
			sooper.define('TestClass', {
				implements: TestInterface,
				testFunc: function me(value) {
					return me.super.call(this,value) + 1;
				}
			});
			var test = new TestClass();
			expect(test.testFunc(1)).toBe(3);
		});
	});
});
<|endoftext|>


<commit_before>function degToRad(deg) {
    return deg * Math.PI / 180;
}

function radToDeg(rad) {
    return rad * 180 / Math.PI;
}

function normalizeAngle(angle) {
    while (angle > 2 * Math.PI) {
        angle -= 2 * Math.PI;
    }
    while (angle < 0) {
        angle += 2 * Math.PI;
    }
    return angle;
}

function reportedWindDirection(direction) {
    return normalizeAngle(direction + Math.PI);
}

function clamp(value, min, max) {
    return Math.min(Math.max(value, min), max);
}

function isDialogOpen(id) {
    var $id = $(id);
    return $id.data("ui-dialog") && $id.dialog("isOpen");
}

function createLatLng(coords) {
    return new google.maps.LatLng(coords[0], coords[1]);
}

function metersToFeet(meters) {
    return meters * 3.2808399;
}

function metersPerSecToMilesPerHour(metersPerSec) {
    return metersPerSec * 2.23693629;
}

function formatSpeed(metersPerSec, significantDigits) {
    significantDigits = significantDigits || 0;
    return viewModel.display.useMetric()
        ? $.number(metersPerSec, significantDigits) + " " + localize("ms")
        : $.number(metersPerSecToMilesPerHour(metersPerSec), significantDigits) + " " + localize("mph");
}

function formatAltitude(meters, significantDigits) {
    significantDigits = significantDigits || 0;
    return viewModel.display.useMetric()
        ? $.number(meters, significantDigits) + " " + localize("m")
        : $.number(metersToFeet(meters), significantDigits) + " " + localize("ft");
}

function formatHeading(angle, significantDigits) {
    significantDigits = significantDigits || 0;
    return $.number(radToDeg(angle), significantDigits) + "°";
}

function formatSimulationSpeed(speed, significantDigits) {
    significantDigits = significantDigits || 1;
    return $.number(speed, significantDigits) + "x" + (speed == 0 ? " " + localize("paused") : "");
}

function formatCoords(latlng, significantDigits) {
    significantDigits = significantDigits || 6;
    if (!latlng) {
        return '';
    }
    return '('
        + $.number(latlng.lat(), significantDigits) + ', '
        + $.number(latlng.lng(), significantDigits)
        + ')';
}

function createBlueSkiesControl(element, callback) {
    var $frame = $(element).children("iframe");
    $frame.load(function() {
        var contentWindow = $frame.get(0).contentWindow,
            viewModel = contentWindow.viewModel;
        contentWindow.ko.applyBindings(viewModel, $(element).get(0));
        if (callback) {
            callback(viewModel);
        }
    });
}
<commit_msg>Support jQuery object as a parameter<commit_after>function degToRad(deg) {
    return deg * Math.PI / 180;
}

function radToDeg(rad) {
    return rad * 180 / Math.PI;
}

function normalizeAngle(angle) {
    while (angle > 2 * Math.PI) {
        angle -= 2 * Math.PI;
    }
    while (angle < 0) {
        angle += 2 * Math.PI;
    }
    return angle;
}

function reportedWindDirection(direction) {
    return normalizeAngle(direction + Math.PI);
}

function clamp(value, min, max) {
    return Math.min(Math.max(value, min), max);
}

function isDialogOpen(id) {
    var $id = $(id);
    return $id.data("ui-dialog") && $id.dialog("isOpen");
}

function createLatLng(coords) {
    return new google.maps.LatLng(coords[0], coords[1]);
}

function metersToFeet(meters) {
    return meters * 3.2808399;
}

function metersPerSecToMilesPerHour(metersPerSec) {
    return metersPerSec * 2.23693629;
}

function formatSpeed(metersPerSec, significantDigits) {
    significantDigits = significantDigits || 0;
    return viewModel.display.useMetric()
        ? $.number(metersPerSec, significantDigits) + " " + localize("ms")
        : $.number(metersPerSecToMilesPerHour(metersPerSec), significantDigits) + " " + localize("mph");
}

function formatAltitude(meters, significantDigits) {
    significantDigits = significantDigits || 0;
    return viewModel.display.useMetric()
        ? $.number(meters, significantDigits) + " " + localize("m")
        : $.number(metersToFeet(meters), significantDigits) + " " + localize("ft");
}

function formatHeading(angle, significantDigits) {
    significantDigits = significantDigits || 0;
    return $.number(radToDeg(angle), significantDigits) + "°";
}

function formatSimulationSpeed(speed, significantDigits) {
    significantDigits = significantDigits || 1;
    return $.number(speed, significantDigits) + "x" + (speed == 0 ? " " + localize("paused") : "");
}

function formatCoords(latlng, significantDigits) {
    significantDigits = significantDigits || 6;
    if (!latlng) {
        return '';
    }
    return '('
        + $.number(latlng.lat(), significantDigits) + ', '
        + $.number(latlng.lng(), significantDigits)
        + ')';
}

function createBlueSkiesControl(element, callback) {
    var $frame = $(element).children("iframe");
    $frame.load(function() {
        var $parent = $(this).parent(),
            contentWindow = this.contentWindow,
            viewModel = contentWindow.viewModel;
        contentWindow.ko.applyBindings(viewModel, $parent.get(0));
        if (callback) {
            callback(viewModel);
        }
    });
}
<|endoftext|>


<commit_before>/* @flow */

import { assert, warn } from './util/warn'
import { cleanPath } from './util/path'

export function createRouteMap (
  routes: Array<RouteConfig>,
  oldPathMap?: Dictionary<RouteRecord>,
  oldNameMap?: Dictionary<RouteRecord>
): {
  pathMap: Dictionary<RouteRecord>;
  nameMap: Dictionary<RouteRecord>;
} {
  const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null)
  const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null)

  routes.forEach(route => {
    addRouteRecord(pathMap, nameMap, route)
  })

  return {
    pathMap,
    nameMap
  }
}

function addRouteRecord (
  pathMap: Dictionary<RouteRecord>,
  nameMap: Dictionary<RouteRecord>,
  route: RouteConfig,
  parent?: RouteRecord,
  matchAs?: string
) {
  const { path, name } = route
  if (process.env.NODE_ENV !== 'production') {
    assert(path != null, `"path" is required in a route configuration.`)
    assert(
      typeof route.component !== 'string',
      `route config "component" for path: ${String(path || name)} cannot be a ` +
      `string id. Use an actual component instead.`
    )
  }

  const record: RouteRecord = {
    path: normalizePath(path, parent),
    components: route.components || { default: route.component },
    instances: {},
    name,
    parent,
    matchAs,
    redirect: route.redirect,
    beforeEnter: route.beforeEnter,
    meta: route.meta || {},
    props: route.props == null
      ? {}
      : route.components
        ? route.props
        : { default: route.props }
  }

  if (route.children) {
    // Warn if route is named and has a default child route.
    // If users navigate to this route by name, the default child will
    // not be rendered (GH Issue #629)
    if (process.env.NODE_ENV !== 'production') {
      if (route.name && route.children.some(child => /^\/?$/.test(child.path))) {
        warn(
          false,
          `Named Route '${route.name}' has a default child route. ` +
          `When navigating to this named route (:to="{name: '${route.name}'"), ` +
          `the default child route will not be rendered. Remove the name from ` +
          `this route and use the name of the default child route for named ` +
          `links instead.`
        )
      }
    }
    route.children.forEach(child => {
      const childMatchAs = matchAs
        ? cleanPath(`${matchAs}/${child.path}`)
        : undefined
      addRouteRecord(pathMap, nameMap, child, record, childMatchAs)
    })
  }

  if (route.alias !== undefined) {
    if (Array.isArray(route.alias)) {
      route.alias.forEach(alias => {
        const aliasRoute = {
          path: alias,
          children: route.children
        }
        addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path)
      })
    } else {
      const aliasRoute = {
        path: route.alias,
        children: route.children
      }
      addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path)
    }
  }

  if (!pathMap[record.path]) {
    pathMap[record.path] = record
  }

  if (name) {
    if (!nameMap[name]) {
      nameMap[name] = record
    } else if (process.env.NODE_ENV !== 'production') {
      warn(
        false,
        `Duplicate named routes definition: ` +
        `{ name: "${name}", path: "${record.path}" }`
      )
    }
  }
}

function normalizePath (path: string, parent?: RouteRecord): string {
  path = path.replace(/\/$/, '')
  if (path[0] === '/') return path
  if (parent == null) return path
  return cleanPath(`${parent.path}/${path}`)
}
<commit_msg>avoid warning aliased child routes with name (fix #1119)<commit_after>/* @flow */

import { assert, warn } from './util/warn'
import { cleanPath } from './util/path'

export function createRouteMap (
  routes: Array<RouteConfig>,
  oldPathMap?: Dictionary<RouteRecord>,
  oldNameMap?: Dictionary<RouteRecord>
): {
  pathMap: Dictionary<RouteRecord>;
  nameMap: Dictionary<RouteRecord>;
} {
  const pathMap: Dictionary<RouteRecord> = oldPathMap || Object.create(null)
  const nameMap: Dictionary<RouteRecord> = oldNameMap || Object.create(null)

  routes.forEach(route => {
    addRouteRecord(pathMap, nameMap, route)
  })

  return {
    pathMap,
    nameMap
  }
}

function addRouteRecord (
  pathMap: Dictionary<RouteRecord>,
  nameMap: Dictionary<RouteRecord>,
  route: RouteConfig,
  parent?: RouteRecord,
  matchAs?: string
) {
  const { path, name } = route
  if (process.env.NODE_ENV !== 'production') {
    assert(path != null, `"path" is required in a route configuration.`)
    assert(
      typeof route.component !== 'string',
      `route config "component" for path: ${String(path || name)} cannot be a ` +
      `string id. Use an actual component instead.`
    )
  }

  const record: RouteRecord = {
    path: normalizePath(path, parent),
    components: route.components || { default: route.component },
    instances: {},
    name,
    parent,
    matchAs,
    redirect: route.redirect,
    beforeEnter: route.beforeEnter,
    meta: route.meta || {},
    props: route.props == null
      ? {}
      : route.components
        ? route.props
        : { default: route.props }
  }

  if (route.children) {
    // Warn if route is named and has a default child route.
    // If users navigate to this route by name, the default child will
    // not be rendered (GH Issue #629)
    if (process.env.NODE_ENV !== 'production') {
      if (route.name && route.children.some(child => /^\/?$/.test(child.path))) {
        warn(
          false,
          `Named Route '${route.name}' has a default child route. ` +
          `When navigating to this named route (:to="{name: '${route.name}'"), ` +
          `the default child route will not be rendered. Remove the name from ` +
          `this route and use the name of the default child route for named ` +
          `links instead.`
        )
      }
    }
    route.children.forEach(child => {
      const childMatchAs = matchAs
        ? cleanPath(`${matchAs}/${child.path}`)
        : undefined
      addRouteRecord(pathMap, nameMap, child, record, childMatchAs)
    })
  }

  if (route.alias !== undefined) {
    if (Array.isArray(route.alias)) {
      route.alias.forEach(alias => {
        const aliasRoute = {
          path: alias,
          children: route.children
        }
        addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path)
      })
    } else {
      const aliasRoute = {
        path: route.alias,
        children: route.children
      }
      addRouteRecord(pathMap, nameMap, aliasRoute, parent, record.path)
    }
  }

  if (!pathMap[record.path]) {
    pathMap[record.path] = record
  }

  if (name) {
    if (!nameMap[name]) {
      nameMap[name] = record
    } else if (process.env.NODE_ENV !== 'production' && !matchAs) {
      warn(
        false,
        `Duplicate named routes definition: ` +
        `{ name: "${name}", path: "${record.path}" }`
      )
    }
  }
}

function normalizePath (path: string, parent?: RouteRecord): string {
  path = path.replace(/\/$/, '')
  if (path[0] === '/') return path
  if (parent == null) return path
  return cleanPath(`${parent.path}/${path}`)
}
<|endoftext|>


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

if (!window.location.origin) {
  window.location.origin =
      window.location.protocol + "//" +
      window.location.hostname +
      (window.location.port ? (':' + window.location.port) : '');
}

Elm.Debugger = null;
Elm.debuggerAttach = function(module, hotSwapState /* =undefined */) {
  return {
    make: function(runtime) {
      var wrappedModule = debugModule(module, runtime);
      Elm.Debugger = debuggerInit(wrappedModule, runtime, hotSwapState);
      dispatchElmDebuggerInit();
      return wrappedModule.debuggedModule;
    }
  };
};

var EVENTS_PER_SAVE = 100;
var eventCounter = 0;

function dispatchElmDebuggerInit() {
  if (parent.window) {
    var dispatch = function() {
      parent.window.postMessage("elmDebuggerInit", window.location.origin);
    };
    if (parent.window.document.readyState === "complete") {
      dispatch();
    }
    else {
      parent.window.addEventListener("load", dispatch);
    }
  }
}

function debugModule(module, runtime) {
  var programPaused = false;
  var recordedEvents = [];
  var asyncCallbacks = [];
  var snapshots = [];
  var watchTracker = Elm.Native.Debug.make(runtime).watchTracker;
  var pauseTime = 0;
  var eventsUntilSnapshot = EVENTS_PER_SAVE;

  // runtime is the prototype of wrappedRuntime
  // so we can access all runtime properties too
  var wrappedRuntime = Object.create(runtime);
  wrappedRuntime.notify = wrapNotify;
  wrappedRuntime.runDelayed = wrapRunDelayed;

  // make a copy of the wrappedRuntime
  var assignedPropTracker = Object.create(wrappedRuntime);
  var debuggedModule = module.make(assignedPropTracker);

  // make sure the signal graph is actually a signal & extract the visual model
  if ( !('recv' in debuggedModule.main) ) {
    debuggedModule.main = Elm.Signal.make(runtime).constant(debuggedModule.main);
  }

  // The main module stores imported modules onto the runtime.
  // To ensure only one instance of each module is created,
  // we assign them back on the original runtime object.
  Object.keys(assignedPropTracker).forEach(function(key) {
    runtime[key] = assignedPropTracker[key];
  });

  var signalGraphNodes = flattenSignalGraph(wrappedRuntime.inputs);
  var tracePath = tracePathInit(runtime, debuggedModule.main);

  snapshots.push(snapshotSignalGraph(signalGraphNodes));

  function wrapNotify(id, v) {
    var timestep = runtime.timer.now();

    if (programPaused) {
      // ignore async events generated while playing back
      // or user events while program is paused
      return false;
    }
    else {
      recordEvent(id, v, timestep);
      var changed = runtime.notify(id, v, timestep);
      if (eventsUntilSnapshot === 1) {
        saveSnapshot();
        eventsUntilSnapshot = EVENTS_PER_SAVE;
      } else {
        eventsUntilSnapshot -= 1;
      }
      if (parent.window) {
        parent.window.postMessage("elmNotify", window.location.origin);
      }
      return changed;
    }
  };

  function wrapRunDelayed(func, delayMs) {
    if (programPaused) {
      // Don't push timers and such to the callback stack while we're paused.
      // It causes too many callbacks to be fired during unpausing.
      return 0;
    }
    var cbObj = { func:func, delayMs:delayMs, timerId:0, executed:false };
    var timerId = setTimeout(function() {
        cbObj.executed = true;
        func();
      }, delayMs);
    cbObj.timerId = timerId;
    asyncCallbacks.push(cbObj);
    return timerId;
  }

  function recordEvent(id, v, timestep) {
    watchTracker.pushFrame();
    recordedEvents.push({ id:id, value:v, timestep:timestep });
    eventCounter += 1;
  }

  function clearAsyncCallbacks() {
    asyncCallbacks.forEach(function(timer) {
      if (!timer.executed) {
        clearTimeout(timer.timerId);
      }
    });
  }

  function clearRecordedEvents() {
    recordedEvents = [];
    eventCounter = 0;
  }

  function getRecordedEventsLength() {
    return recordedEvents.length;
  }

  function getRecordedEventAt(i) {
    return recordedEvents[i];
  }

  function copyRecordedEvents() {
    return recordedEvents.slice();
  }

  function loadRecordedEvents(events) {
    recordedEvents = events.slice();
  }

  function clearSnapshots() {
    snapshots = [snapshotSignalGraph(signalGraphNodes)];
  }

  function getSnapshotAt(i) {
    var snapshotEvent = Math.floor(i / EVENTS_PER_SAVE);
    assert(snapshotEvent < snapshots.length && snapshotEvent >= 0, "Out of bounds index: " + snapshotEvent);
    return snapshots[snapshotEvent];
  }

  function saveSnapshot() {
    snapshots.push(snapshotSignalGraph(signalGraphNodes));
  }

  function setPaused() {
    programPaused = true;
    clearAsyncCallbacks();
    tracePath.stopRecording();
    pauseTime = Date.now();
  }

  function setContinue(position) {
    var timerDelay = Date.now() - pauseTime;
    runtime.timer.addDelay(timerDelay);
    programPaused = false;
    if (position > 0) {
      // If we're not unpausing at the head, then we need to dump the
      // events that are ahead of where we're continuing.
      var lastSnapshotPosition = Math.ceil(position / EVENTS_PER_SAVE);
      eventsUntilSnapshot = EVENTS_PER_SAVE - (position % EVENTS_PER_SAVE);
      snapshots = snapshots.slice(0, lastSnapshotPosition);
      recordedEvents = recordedEvents.slice(0, position);
      tracePath.clearTracesAfter(position);
      eventCounter = position;
      executeCallbacks(asyncCallbacks, false);
    }
    tracePath.startRecording();
  }

  function getPaused() {
    return programPaused;
  }

  return {
    debuggedModule: debuggedModule,
    signalGraphNodes: signalGraphNodes,
    initialSnapshot: snapshotSignalGraph(signalGraphNodes),
    initialAsyncCallbacks: asyncCallbacks.slice(),
    // API functions
    clearAsyncCallbacks: clearAsyncCallbacks,
    clearRecordedEvents: clearRecordedEvents,
    getRecordedEventsLength: getRecordedEventsLength,
    getRecordedEventAt: getRecordedEventAt,
    copyRecordedEvents: copyRecordedEvents,
    loadRecordedEvents: loadRecordedEvents,
    clearSnapshots: clearSnapshots,
    getSnapshotAt: getSnapshotAt,
    saveSnapshot: saveSnapshot,
    getPaused: getPaused,
    setPaused: setPaused,
    setContinue: setContinue,
    tracePath: tracePath,
    watchTracker: watchTracker
  };
}

function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
  var currentEventIndex = 0;

  function resetProgram(position) {
    var closestSnapshot = debugModule.getSnapshotAt(position);
    debugModule.clearAsyncCallbacks();
    restoreSnapshot(debugModule.signalGraphNodes, closestSnapshot);
    redrawGraphics();
  }

  function restartProgram() {
    resetProgram(0);
    debugModule.watchTracker.clear();
    debugModule.tracePath.clearTraces();
    debugModule.clearRecordedEvents();
    debugModule.clearSnapshots();
    debugModule.setContinue(0);
    executeCallbacks(debugModule.initialAsyncCallbacks, true);
  }

  function pauseProgram() {
    debugModule.setPaused();
    currentEventIndex = debugModule.getRecordedEventsLength();
  }

  function continueProgram() {
    if (debugModule.getPaused())
    {
      if (currentEventIndex === 0) {
        restartProgram();
        return;
      }
      var closestSnapshotIndex = Math.floor(currentEventIndex / EVENTS_PER_SAVE) * EVENTS_PER_SAVE;
      resetProgram(currentEventIndex);
      var continueIndex = currentEventIndex;
      currentEventIndex = closestSnapshotIndex;
      stepTo(continueIndex);
      debugModule.setContinue(currentEventIndex);
    }
  }

  function stepTo(index) {
    if (!debugModule.getPaused()) {
      debugModule.setPaused();
      resetProgram();
    }

    if (index < 0 || index > getMaxSteps()) {
      throw "Index out of bounds: " + index;
    }

    if (index < currentEventIndex) {
      var closestSnapshotIndex = Math.floor(index / EVENTS_PER_SAVE) * EVENTS_PER_SAVE;
      resetProgram(index);
      currentEventIndex = closestSnapshotIndex;
    }

    while (currentEventIndex < index) {
      var nextEvent = debugModule.getRecordedEventAt(currentEventIndex);
      runtime.notify(nextEvent.id, nextEvent.value, nextEvent.timestep);

      currentEventIndex += 1;
    }
  }

  function getMaxSteps() {
    return debugModule.getRecordedEventsLength();
  }

  function redrawGraphics() {
    var main = debugModule.debuggedModule.main
    for (var i = main.kids.length ; i-- ; ) {
      main.kids[i].recv(runtime.timer.now(), true, main.id);
    }
  }

  function getHotSwapState() {
    var continueIndex = currentEventIndex;
    if (!debugModule.getPaused()) {
      continueIndex = getMaxSteps();
    }
    return {
      recordedEvents: debugModule.copyRecordedEvents(),
      currentEventIndex: continueIndex
    };
  }

  function dispose() {
    var parentNode = runtime.node.parentNode;
    parentNode.removeChild(debugModule.tracePath.canvas);
    parentNode.removeChild(runtime.node);
  }

  if (hotSwapState) {
    // The problem is that we want to previous paused state. But
    // by the time JS reaches here, the old code has been swapped out
    // and the new modules are being generated. So we can ask the
    // debugging console what it thinks the pause state is and go
    // from there.
    var paused = top.debug.paused;
    debugModule.setPaused();
    debugModule.loadRecordedEvents(hotSwapState.recordedEvents);
    var index = getMaxSteps();
    var eventsUntilSnapshot = EVENTS_PER_SAVE;
    eventCounter = 0;
    debugModule.tracePath.clearTraces();

    // draw new trace path
    debugModule.tracePath.startRecording();
    while(currentEventIndex < index) {
      var nextEvent = debugModule.getRecordedEventAt(currentEventIndex);
      eventCounter += 1;
      runtime.notify(nextEvent.id, nextEvent.value, nextEvent.timestep);
      if (eventsUntilSnapshot === 1) {
        debugModule.saveSnapshot();
        eventsUntilSnapshot = EVENTS_PER_SAVE;
      } else {
        eventsUntilSnapshot -= 1;
      }
      currentEventIndex += 1;
    }
    debugModule.tracePath.stopRecording();

    stepTo(hotSwapState.currentEventIndex);
    if (!paused) {
      debugModule.setContinue(hotSwapState.currentEventIndex);
    }
  }

  runtime.node.parentNode.appendChild(debugModule.tracePath.canvas);

  var elmDebugger = {
      restart: restartProgram,
      pause: pauseProgram,
      kontinue: continueProgram,
      getMaxSteps: getMaxSteps,
      stepTo: stepTo,
      getPaused: debugModule.getPaused,
      getHotSwapState: getHotSwapState,
      dispose: dispose,
      allNodes: debugModule.signalGraphNodes,
      watchTracker: debugModule.watchTracker
  };

  return elmDebugger;
}

function Point(x, y) {
  this.x = x;
  this.y = y;

  this.translate = function(x, y) {
    return new Point(this.x + x, this.y + y);
  }

  this.equals = function(p) {
    return this.x == p.x && this.y == p.y;
  }
}

function tracePathInit(runtime, signalGraphMain) {
  var List = Elm.List.make(runtime);
  var Signal = Elm.Signal.make(runtime);
  var tracePathNode = A2(Signal.lift, graphicsUpdate, signalGraphMain);
  var tracePathCanvas = createCanvas();
  var tracePositions = {};
  var recordingTraces = true;

  function findPositions(currentScene) {
    var positions = {};
    function processElement(elem, offset) {
      if (elem.element.ctor == "Custom" && elem.element.type == "Collage")
      {
        List.map(F2(processForm)(offset))(elem.element.model.forms);
      }
      if (elem.props.debugTracePathId)
      {
        positions[elem.props.debugTracePathId] = new Point(offset.x, offset.y);
      }
    }

    function processForm(offset, form) {
      if (form.form.ctor == "FElement")
      {
        processElement(form.form._0, offset.translate(form.x, -form.y));
      }
    }

    processElement(currentScene, new Point(0, 0));
    return positions;
  }

  function appendPositions(positions) {
    for (var id in positions) {
      var pos = positions[id];
      if (tracePositions.hasOwnProperty(id)) {
        tracePositions[id].push(pos);
      }
      else {
        tracePositions[id] = [pos];
      }
      if (tracePositions[id].length < eventCounter) {
        var padCount = eventCounter - tracePositions[id].length;
        var lastTracePosition = tracePositions[id][tracePositions[id].length - 1];
        for (var i = padCount; i--;) {
          tracePositions[id].push(lastTracePosition)
        }
      }
      assert(tracePositions[id].length === eventCounter, "We don't have a 1-1 mapping of trace positions to events")
    }
  }

  function graphicsUpdate(currentScene) {
    if (!recordingTraces) {
      return;
    }

    var ctx = tracePathCanvas.getContext('2d');
    ctx.clearRect(0, 0, tracePathCanvas.width, tracePathCanvas.height);

    ctx.save();
    ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
    appendPositions(findPositions(currentScene));
    for (var id in tracePositions)
    {
      ctx.beginPath();
      var points = tracePositions[id];
      for (var i=0; i < points.length; i++)
      {
        var p = points[i];
        if (i == 0) {
          ctx.moveTo(p.x, p.y);
        }
        else {
          ctx.lineTo(p.x, p.y);
        }
      }
      ctx.lineWidth = 1;
      ctx.strokeStyle = "rgba(50, 50, 50, 0.4)";
      ctx.stroke();

      for (var i=0; i < points.length; i++)
      {
        var p = points[i];
        ctx.beginPath();
        ctx.arc(p.x, p.y, 2, 0, Math.PI * 2);
        ctx.fillStyle = "rgba(50, 50, 50, 0.4)";
        ctx.fill();
      }
    }

    ctx.restore();
  }

  function clearTraces() {
    tracePositions = {};
  }

  function stopRecording() {
    recordingTraces = false;
  }

  function startRecording() {
    recordingTraces = true;
  }

  function clearTracesAfter(position) {
    var newTraces = {};
    for (var id in tracePositions) {
      newTraces[id] = tracePositions[id].slice(0,position);
    }
    tracePositions = newTraces;
  }

  return {
    graphicsUpdate: graphicsUpdate,
    canvas: tracePathCanvas,
    clearTraces: clearTraces,
    clearTracesAfter: clearTracesAfter,
    stopRecording: stopRecording,
    startRecording: startRecording
  }
}

function executeCallbacks(callbacks, reexecute) {
  callbacks.forEach(function(timer) {
    if (reexecute || !timer.executed) {
      var func = timer.func;
      timer.executed = true;
      func();
    }
  });
}

function createCanvas() {
  var c = document.createElement('canvas');
  c.width = window.innerWidth;
  c.height = window.innerHeight;
  c.style.position = "absolute";
  c.style.top = "0";
  c.style.left = "0";
  c.style.pointerEvents = "none";
  return c;
}

function assert(bool, msg) {
  if (!bool) {
    throw "Assertion error: " + msg;
  }
}

function snapshotSignalGraph(signalGraphNodes) {
  var nodeValues = [];

  signalGraphNodes.forEach(function(node) {
    nodeValues.push({ value: node.value, id: node.id });
  });

  return nodeValues;
};

function restoreSnapshot(signalGraphNodes, snapshot) {
  assert(signalGraphNodes.length == snapshot.length, "saved program state has wrong length");
  for (var i=0; i < signalGraphNodes.length; i++) {
    var node = signalGraphNodes[i];
    var state = snapshot[i];
    assert(node.id == state.id, "the nodes moved position");

    node.value = state.value;
  }
}

function flattenSignalGraph(nodes) {
  var nodesById = {};

  function addAllToDict(node) {
    nodesById[node.id] = node;
    node.kids.forEach(addAllToDict);
  }
  nodes.forEach(addAllToDict);

  var allNodes = Object.keys(nodesById).sort().map(function(key) {
    return nodesById[key];
  });
  return allNodes;
};

}());
<commit_msg>line length reduction. No more reckless 150 character lines.<commit_after>(function() {
'use strict';

if (!window.location.origin) {
  window.location.origin =
      window.location.protocol + "//" +
      window.location.hostname +
      (window.location.port ? (':' + window.location.port) : '');
}

Elm.Debugger = null;
Elm.debuggerAttach = function(module, hotSwapState /* =undefined */) {
  return {
    make: function(runtime) {
      var wrappedModule = debugModule(module, runtime);
      Elm.Debugger = debuggerInit(wrappedModule, runtime, hotSwapState);
      dispatchElmDebuggerInit();
      return wrappedModule.debuggedModule;
    }
  };
};

var EVENTS_PER_SAVE = 100;
var eventCounter = 0;

function dispatchElmDebuggerInit() {
  if (parent.window) {
    var dispatch = function() {
      parent.window.postMessage("elmDebuggerInit", window.location.origin);
    };
    if (parent.window.document.readyState === "complete") {
      dispatch();
    }
    else {
      parent.window.addEventListener("load", dispatch);
    }
  }
}

function debugModule(module, runtime) {
  var programPaused = false;
  var recordedEvents = [];
  var asyncCallbacks = [];
  var snapshots = [];
  var watchTracker = Elm.Native.Debug.make(runtime).watchTracker;
  var pauseTime = 0;
  var eventsUntilSnapshot = EVENTS_PER_SAVE;

  // runtime is the prototype of wrappedRuntime
  // so we can access all runtime properties too
  var wrappedRuntime = Object.create(runtime);
  wrappedRuntime.notify = wrapNotify;
  wrappedRuntime.runDelayed = wrapRunDelayed;

  // make a copy of the wrappedRuntime
  var assignedPropTracker = Object.create(wrappedRuntime);
  var debuggedModule = module.make(assignedPropTracker);

  // make sure the signal graph is actually a signal & extract the visual model
  if ( !('recv' in debuggedModule.main) ) {
    debuggedModule.main = Elm.Signal.make(runtime).constant(debuggedModule.main);
  }

  // The main module stores imported modules onto the runtime.
  // To ensure only one instance of each module is created,
  // we assign them back on the original runtime object.
  Object.keys(assignedPropTracker).forEach(function(key) {
    runtime[key] = assignedPropTracker[key];
  });

  var signalGraphNodes = flattenSignalGraph(wrappedRuntime.inputs);
  var tracePath = tracePathInit(runtime, debuggedModule.main);

  snapshots.push(snapshotSignalGraph(signalGraphNodes));

  function wrapNotify(id, v) {
    var timestep = runtime.timer.now();

    if (programPaused) {
      // ignore async events generated while playing back
      // or user events while program is paused
      return false;
    }
    else {
      recordEvent(id, v, timestep);
      var changed = runtime.notify(id, v, timestep);
      if (eventsUntilSnapshot === 1) {
        saveSnapshot();
        eventsUntilSnapshot = EVENTS_PER_SAVE;
      } else {
        eventsUntilSnapshot -= 1;
      }
      if (parent.window) {
        parent.window.postMessage("elmNotify", window.location.origin);
      }
      return changed;
    }
  };

  function wrapRunDelayed(func, delayMs) {
    if (programPaused) {
      // Don't push timers and such to the callback stack while we're paused.
      // It causes too many callbacks to be fired during unpausing.
      return 0;
    }
    var cbObj = { func:func, delayMs:delayMs, timerId:0, executed:false };
    var timerId = setTimeout(function() {
        cbObj.executed = true;
        func();
      }, delayMs);
    cbObj.timerId = timerId;
    asyncCallbacks.push(cbObj);
    return timerId;
  }

  function recordEvent(id, v, timestep) {
    watchTracker.pushFrame();
    recordedEvents.push({ id:id, value:v, timestep:timestep });
    eventCounter += 1;
  }

  function clearAsyncCallbacks() {
    asyncCallbacks.forEach(function(timer) {
      if (!timer.executed) {
        clearTimeout(timer.timerId);
      }
    });
  }

  function clearRecordedEvents() {
    recordedEvents = [];
    eventCounter = 0;
  }

  function getRecordedEventsLength() {
    return recordedEvents.length;
  }

  function getRecordedEventAt(i) {
    return recordedEvents[i];
  }

  function copyRecordedEvents() {
    return recordedEvents.slice();
  }

  function loadRecordedEvents(events) {
    recordedEvents = events.slice();
  }

  function clearSnapshots() {
    snapshots = [snapshotSignalGraph(signalGraphNodes)];
  }

  function getSnapshotAt(i) {
    var snapshotEvent = Math.floor(i / EVENTS_PER_SAVE);
    assert(snapshotEvent < snapshots.length && snapshotEvent >= 0,
           "Out of bounds index: " + snapshotEvent);
    return snapshots[snapshotEvent];
  }

  function saveSnapshot() {
    snapshots.push(snapshotSignalGraph(signalGraphNodes));
  }

  function setPaused() {
    programPaused = true;
    clearAsyncCallbacks();
    tracePath.stopRecording();
    pauseTime = Date.now();
  }

  function setContinue(position) {
    var timerDelay = Date.now() - pauseTime;
    runtime.timer.addDelay(timerDelay);
    programPaused = false;
    if (position > 0) {
      // If we're not unpausing at the head, then we need to dump the
      // events that are ahead of where we're continuing.
      var lastSnapshotPosition = Math.ceil(position / EVENTS_PER_SAVE);
      eventsUntilSnapshot = EVENTS_PER_SAVE - (position % EVENTS_PER_SAVE);
      snapshots = snapshots.slice(0, lastSnapshotPosition);
      recordedEvents = recordedEvents.slice(0, position);
      tracePath.clearTracesAfter(position);
      eventCounter = position;
      executeCallbacks(asyncCallbacks, false);
    }
    tracePath.startRecording();
  }

  function getPaused() {
    return programPaused;
  }

  return {
    debuggedModule: debuggedModule,
    signalGraphNodes: signalGraphNodes,
    initialSnapshot: snapshotSignalGraph(signalGraphNodes),
    initialAsyncCallbacks: asyncCallbacks.slice(),
    // API functions
    clearAsyncCallbacks: clearAsyncCallbacks,
    clearRecordedEvents: clearRecordedEvents,
    getRecordedEventsLength: getRecordedEventsLength,
    getRecordedEventAt: getRecordedEventAt,
    copyRecordedEvents: copyRecordedEvents,
    loadRecordedEvents: loadRecordedEvents,
    clearSnapshots: clearSnapshots,
    getSnapshotAt: getSnapshotAt,
    saveSnapshot: saveSnapshot,
    getPaused: getPaused,
    setPaused: setPaused,
    setContinue: setContinue,
    tracePath: tracePath,
    watchTracker: watchTracker
  };
}

function debuggerInit(debugModule, runtime, hotSwapState /* =undefined */) {
  var currentEventIndex = 0;

  function resetProgram(position) {
    var closestSnapshot = debugModule.getSnapshotAt(position);
    debugModule.clearAsyncCallbacks();
    restoreSnapshot(debugModule.signalGraphNodes, closestSnapshot);
    redrawGraphics();
  }

  function restartProgram() {
    resetProgram(0);
    debugModule.watchTracker.clear();
    debugModule.tracePath.clearTraces();
    debugModule.clearRecordedEvents();
    debugModule.clearSnapshots();
    debugModule.setContinue(0);
    executeCallbacks(debugModule.initialAsyncCallbacks, true);
  }

  function pauseProgram() {
    debugModule.setPaused();
    currentEventIndex = debugModule.getRecordedEventsLength();
  }

  function continueProgram() {
    if (debugModule.getPaused())
    {
      if (currentEventIndex === 0) {
        restartProgram();
        return;
      }
      var closestSnapshotIndex =
          Math.floor(currentEventIndex / EVENTS_PER_SAVE) * EVENTS_PER_SAVE;
      resetProgram(currentEventIndex);
      var continueIndex = currentEventIndex;
      currentEventIndex = closestSnapshotIndex;
      stepTo(continueIndex);
      debugModule.setContinue(currentEventIndex);
    }
  }

  function stepTo(index) {
    if (!debugModule.getPaused()) {
      debugModule.setPaused();
      resetProgram();
    }

    if (index < 0 || index > getMaxSteps()) {
      throw "Index out of bounds: " + index;
    }

    if (index < currentEventIndex) {
      var closestSnapshotIndex = Math.floor(index / EVENTS_PER_SAVE) * EVENTS_PER_SAVE;
      resetProgram(index);
      currentEventIndex = closestSnapshotIndex;
    }

    while (currentEventIndex < index) {
      var nextEvent = debugModule.getRecordedEventAt(currentEventIndex);
      runtime.notify(nextEvent.id, nextEvent.value, nextEvent.timestep);

      currentEventIndex += 1;
    }
  }

  function getMaxSteps() {
    return debugModule.getRecordedEventsLength();
  }

  function redrawGraphics() {
    var main = debugModule.debuggedModule.main
    for (var i = main.kids.length ; i-- ; ) {
      main.kids[i].recv(runtime.timer.now(), true, main.id);
    }
  }

  function getHotSwapState() {
    var continueIndex = currentEventIndex;
    if (!debugModule.getPaused()) {
      continueIndex = getMaxSteps();
    }
    return {
      recordedEvents: debugModule.copyRecordedEvents(),
      currentEventIndex: continueIndex
    };
  }

  function dispose() {
    var parentNode = runtime.node.parentNode;
    parentNode.removeChild(debugModule.tracePath.canvas);
    parentNode.removeChild(runtime.node);
  }

  if (hotSwapState) {
    // The problem is that we want to previous paused state. But
    // by the time JS reaches here, the old code has been swapped out
    // and the new modules are being generated. So we can ask the
    // debugging console what it thinks the pause state is and go
    // from there.
    var paused = top.debug.paused;
    debugModule.setPaused();
    debugModule.loadRecordedEvents(hotSwapState.recordedEvents);
    var index = getMaxSteps();
    var eventsUntilSnapshot = EVENTS_PER_SAVE;
    eventCounter = 0;
    debugModule.tracePath.clearTraces();

    // draw new trace path
    debugModule.tracePath.startRecording();
    while(currentEventIndex < index) {
      var nextEvent = debugModule.getRecordedEventAt(currentEventIndex);
      eventCounter += 1;
      runtime.notify(nextEvent.id, nextEvent.value, nextEvent.timestep);
      if (eventsUntilSnapshot === 1) {
        debugModule.saveSnapshot();
        eventsUntilSnapshot = EVENTS_PER_SAVE;
      } else {
        eventsUntilSnapshot -= 1;
      }
      currentEventIndex += 1;
    }
    debugModule.tracePath.stopRecording();

    stepTo(hotSwapState.currentEventIndex);
    if (!paused) {
      debugModule.setContinue(hotSwapState.currentEventIndex);
    }
  }

  runtime.node.parentNode.appendChild(debugModule.tracePath.canvas);

  var elmDebugger = {
      restart: restartProgram,
      pause: pauseProgram,
      kontinue: continueProgram,
      getMaxSteps: getMaxSteps,
      stepTo: stepTo,
      getPaused: debugModule.getPaused,
      getHotSwapState: getHotSwapState,
      dispose: dispose,
      allNodes: debugModule.signalGraphNodes,
      watchTracker: debugModule.watchTracker
  };

  return elmDebugger;
}

function Point(x, y) {
  this.x = x;
  this.y = y;

  this.translate = function(x, y) {
    return new Point(this.x + x, this.y + y);
  }

  this.equals = function(p) {
    return this.x == p.x && this.y == p.y;
  }
}

function tracePathInit(runtime, signalGraphMain) {
  var List = Elm.List.make(runtime);
  var Signal = Elm.Signal.make(runtime);
  var tracePathNode = A2(Signal.lift, graphicsUpdate, signalGraphMain);
  var tracePathCanvas = createCanvas();
  var tracePositions = {};
  var recordingTraces = true;

  function findPositions(currentScene) {
    var positions = {};
    function processElement(elem, offset) {
      if (elem.element.ctor == "Custom" && elem.element.type == "Collage")
      {
        List.map(F2(processForm)(offset))(elem.element.model.forms);
      }
      if (elem.props.debugTracePathId)
      {
        positions[elem.props.debugTracePathId] = new Point(offset.x, offset.y);
      }
    }

    function processForm(offset, form) {
      if (form.form.ctor == "FElement")
      {
        processElement(form.form._0, offset.translate(form.x, -form.y));
      }
    }

    processElement(currentScene, new Point(0, 0));
    return positions;
  }

  function appendPositions(positions) {
    for (var id in positions) {
      var pos = positions[id];
      if (tracePositions.hasOwnProperty(id)) {
        tracePositions[id].push(pos);
      }
      else {
        tracePositions[id] = [pos];
      }
      if (tracePositions[id].length < eventCounter) {
        var padCount = eventCounter - tracePositions[id].length;
        var lastTracePosition = tracePositions[id][tracePositions[id].length - 1];
        for (var i = padCount; i--;) {
          tracePositions[id].push(lastTracePosition)
        }
      }
      assert(tracePositions[id].length === eventCounter,
             "We don't have a 1-1 mapping of trace positions to events");
    }
  }

  function graphicsUpdate(currentScene) {
    if (!recordingTraces) {
      return;
    }

    var ctx = tracePathCanvas.getContext('2d');
    ctx.clearRect(0, 0, tracePathCanvas.width, tracePathCanvas.height);

    ctx.save();
    ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
    appendPositions(findPositions(currentScene));
    for (var id in tracePositions)
    {
      ctx.beginPath();
      var points = tracePositions[id];
      for (var i=0; i < points.length; i++)
      {
        var p = points[i];
        if (i == 0) {
          ctx.moveTo(p.x, p.y);
        }
        else {
          ctx.lineTo(p.x, p.y);
        }
      }
      ctx.lineWidth = 1;
      ctx.strokeStyle = "rgba(50, 50, 50, 0.4)";
      ctx.stroke();

      for (var i=0; i < points.length; i++)
      {
        var p = points[i];
        ctx.beginPath();
        ctx.arc(p.x, p.y, 2, 0, Math.PI * 2);
        ctx.fillStyle = "rgba(50, 50, 50, 0.4)";
        ctx.fill();
      }
    }

    ctx.restore();
  }

  function clearTraces() {
    tracePositions = {};
  }

  function stopRecording() {
    recordingTraces = false;
  }

  function startRecording() {
    recordingTraces = true;
  }

  function clearTracesAfter(position) {
    var newTraces = {};
    for (var id in tracePositions) {
      newTraces[id] = tracePositions[id].slice(0,position);
    }
    tracePositions = newTraces;
  }

  return {
    graphicsUpdate: graphicsUpdate,
    canvas: tracePathCanvas,
    clearTraces: clearTraces,
    clearTracesAfter: clearTracesAfter,
    stopRecording: stopRecording,
    startRecording: startRecording
  }
}

function executeCallbacks(callbacks, reexecute) {
  callbacks.forEach(function(timer) {
    if (reexecute || !timer.executed) {
      var func = timer.func;
      timer.executed = true;
      func();
    }
  });
}

function createCanvas() {
  var c = document.createElement('canvas');
  c.width = window.innerWidth;
  c.height = window.innerHeight;
  c.style.position = "absolute";
  c.style.top = "0";
  c.style.left = "0";
  c.style.pointerEvents = "none";
  return c;
}

function assert(bool, msg) {
  if (!bool) {
    throw "Assertion error: " + msg;
  }
}

function snapshotSignalGraph(signalGraphNodes) {
  var nodeValues = [];

  signalGraphNodes.forEach(function(node) {
    nodeValues.push({ value: node.value, id: node.id });
  });

  return nodeValues;
};

function restoreSnapshot(signalGraphNodes, snapshot) {
  assert(signalGraphNodes.length == snapshot.length,
         "saved program state has wrong length");
  for (var i=0; i < signalGraphNodes.length; i++) {
    var node = signalGraphNodes[i];
    var state = snapshot[i];
    assert(node.id == state.id, "the nodes moved position");

    node.value = state.value;
  }
}

function flattenSignalGraph(nodes) {
  var nodesById = {};

  function addAllToDict(node) {
    nodesById[node.id] = node;
    node.kids.forEach(addAllToDict);
  }
  nodes.forEach(addAllToDict);

  var allNodes = Object.keys(nodesById).sort().map(function(key) {
    return nodesById[key];
  });
  return allNodes;
};

}());
<|endoftext|>


<commit_before>'use strict';

import LessonsComponent from './../components/view-lessons/view-lessons.component';
import LessonComponent from './../components/view-lesson/view-lesson.component';
import LessonEditComponent from './../components/view-lesson-edit/view-lesson-edit.component';
import LessonCreateComponent from './../components/view-lesson-create/view-lesson-create.component';
import LoginComponent from './../components/view-login/view-login.component';
import LandingPageComponent from './../components/view-landing-page/view-landing-page.component';
import RegistrationComponent from './../components/view-registration/view-registration.component'

import LessonsService from './../services/lessons/lessons.service';

resolveLesson.$inject = ['$stateParams', LessonsService.name];
function resolveLesson($stateParams,lessonsService){
    return lessonsService.get($stateParams.lessonId);
}

resolveLessons.$inject = [LessonsService.name];
function resolveLessons(lessonsService){
    return lessonsService.list();
}

config.$inject = ['$stateProvider', '$urlRouterProvider'];
export default function config ($stateProvider, $urlRouterProvider){

    // For any unmatched url, redirect to /home
    $urlRouterProvider.otherwise("/lessons");

    $stateProvider
        .state('lessons', {
            url: '/lessons',
            component: LessonsComponent.name,
            resolve: {
                lessons : resolveLessons
            }
        })
        .state('lessonAdd', {
            url: '/lessons/new',
            component: LessonCreateComponent.name
        })
        .state('lesson', {
            url: '/lessons/:lessonId',
            component: LessonComponent.name,
            resolve: {
                lesson : resolveLesson
            }

        })
        .state('lessonEdit', {
            url: '/lessons/:lessonId/edit',
            component: LessonEditComponent.name,
            resolve: {
                lesson : resolveLesson
            }
        })
        .state('landingPage', {
            url: '/landing',
            component: LandingPageComponent.name,
            resolve: {
                lessons : resolveLessons
            }
        })
        .state('login', {
            url: '/login',
            component: LoginComponent.name,
        })

        .state('register',{
            url: '/register',
            component: RegistrationComponent.name,
        })

}

<commit_msg>Default page made the landing<commit_after>'use strict';

import LessonsComponent from './../components/view-lessons/view-lessons.component';
import LessonComponent from './../components/view-lesson/view-lesson.component';
import LessonEditComponent from './../components/view-lesson-edit/view-lesson-edit.component';
import LessonCreateComponent from './../components/view-lesson-create/view-lesson-create.component';
import LoginComponent from './../components/view-login/view-login.component';
import LandingPageComponent from './../components/view-landing-page/view-landing-page.component';
import RegistrationComponent from './../components/view-registration/view-registration.component'

import LessonsService from './../services/lessons/lessons.service';

resolveLesson.$inject = ['$stateParams', LessonsService.name];
function resolveLesson($stateParams,lessonsService){
    return lessonsService.get($stateParams.lessonId);
}

resolveLessons.$inject = [LessonsService.name];
function resolveLessons(lessonsService){
    return lessonsService.list();
}

config.$inject = ['$stateProvider', '$urlRouterProvider'];
export default function config ($stateProvider, $urlRouterProvider){

    // For any unmatched url, redirect to /home
    $urlRouterProvider.otherwise("/landing");

    $stateProvider
        .state('lessons', {
            url: '/lessons',
            component: LessonsComponent.name,
            resolve: {
                lessons : resolveLessons
            }
        })
        .state('lessonAdd', {
            url: '/lessons/new',
            component: LessonCreateComponent.name
        })
        .state('lesson', {
            url: '/lessons/:lessonId',
            component: LessonComponent.name,
            resolve: {
                lesson : resolveLesson
            }

        })
        .state('lessonEdit', {
            url: '/lessons/:lessonId/edit',
            component: LessonEditComponent.name,
            resolve: {
                lesson : resolveLesson
            }
        })
        .state('landingPage', {
            url: '/landing',
            component: LandingPageComponent.name,
            resolve: {
                lessons : resolveLessons
            }
        })
        .state('login', {
            url: '/login',
            component: LoginComponent.name,
        })

        .state('register',{
            url: '/register',
            component: RegistrationComponent.name,
        })

}

<|endoftext|>


<commit_before>'use strict';
// =========================================================================
//
// Routes for Projects
//
// =========================================================================
var Project     = require ('../controllers/project.controller');
var projectLoad = require ('../controllers/project.load.controller');
var _           = require ('lodash');
var routes = require ('../../../core/server/controllers/core.routes.controller');
var policy = require ('../../../core/server/controllers/core.policy.controller');

module.exports = function (app) {
	routes.setCRUDRoutes (app, 'project', Project, policy);
	//
	// add a phase to a project (from base phase)
	//
	app.route ('/api/project/:project/add/phase/:phaseBaseCode')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.addPhaseWithId (req.params.project, req.params.phaseBaseCode);
		}));
	// remove a phase from a project
	app.route ('/api/project/:project/remove/phase/:phase')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.removePhase (req.params.project, req.params.phase);
		}));
	//
	// start phase
	//
	app.route ('/api/project/:project/start/next/phase')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.startNextPhase (req.params.project);
		}));
	//
	// complete phase
	//
	app.route ('/api/project/:project/complete/phase/:phase')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.completePhase (req.params.project, req.params.phase);
		}));
	//
	// uncomplete phase
	//
	app.route ('/api/project/:project/uncomplete/phase/:phase')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.uncompletePhase (req.params.project, req.params.phase);
		}));
	//
	// get all projects in certain statuses
	//
	app.route ('/api/projects/with/status/:statustoken')
		.all (policy ('user'))
		.get (routes.setAndRun (Project, function (model, req) {
			var opts = {
				initiated      : 'Initiated',
				submitted      : 'Submitted',
				inprogress     : 'In Progress',
				certified      : 'Certified',
				decommissioned : 'Decommissioned'
			};
			var stat = opts[req.params.statustoken] || 'none';
			return model.list ({
				status : stat
			});
		}));
	//
	// publish or unpublish a project
	//
	app.route ('/api/project/:project/publish')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.publish (req.params.Project, true);
		}));
	app.route ('/api/project/:project/unpublish')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.publish (req.params.Project, false);
		}));
	app.route ('/api/project/:project/submit')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.submit (req.params.Project);
		}));
	app.route ('/api/project/bycode/:projectcode')
		.all (policy ('guest'))
		.get (routes.setAndRun (Project, function (model, req) {
			return model.one ({code:req.params.projectcode});
		}));
	// app.route ('/api/')
	// 	.all (policy ('user'))
	// 	.get (function (req, res) {
	// 	var p = new Project (req.user);
	// 	p.list ().then (routes.success(res), routes.failure(res));
	// });

	app.route ('/api/projects/published')
		.get (routes.setAndRun (Project, function (model, req) {
			return model.published ();
		}));

	app.route ('/api/projects/mine')
		.get (routes.setAndRun (Project, function (model, req) {
			return model.mine ();
		}));

	app.route ('/api/projects/lookup')
		.all (policy ('guest'))
		.get (routes.setAndRun (Project, function (model, req) {
			return model.list ({},{_id: 1, code: 1, name: 1, region: 1, status: 1, memPermitID: 1})
			.then ( function(res) {
				var obj = {};
				_.each( res, function(item) {
					obj[item._id] = item;
				});
				return obj;
			});
		}));

	app.route ('/api/projects/regions')
		.all (policy ('user'))
		.get (routes.setAndRun (Project, function (model, req) {
			return model.list ({},{region: 1})
			.then ( function(res) {
				var obj = {};
				_.each( res, function(item) {
					obj[item.region] = item.region;
				});
				return obj;
			});
		}));

	app.route ('/api/projects/import/eao')
		.all (policy ('user'))
		.post (function (req, res) {
			var file = req.files.file;
			if (file) {
				// console.log("Received contact import file:",file);
				routes.setSessionContext(req)
				.then( function (opts) {
					// console.log("opts generated.");
					return projectLoad (file, req, res, opts);
				})
				.then (function (data) {
					// console.log("finished");
					res.json (data);
				});
			}
		});
	app.route ('/api/projects/import/mem')
		.all (policy ('user'))
		.post (function (req, res) {
			var file = req.files.file;
			if (file) {
				// console.log("Received contact import file:",file);
				routes.setSessionContext(req)
				.then( function (opts) {
					// console.log("opts generated.");
					return projectLoad (file, req, res, opts);
				})
				.then (function (data) {
					// console.log("finished");
					res.json (data);
				});
			}
		});
};

<commit_msg>ESM-464, ESM-376: update to the Project server controller to properly pick up the project object and carry on with publish and submit.<commit_after>'use strict';
// =========================================================================
//
// Routes for Projects
//
// =========================================================================
var Project     = require ('../controllers/project.controller');
var projectLoad = require ('../controllers/project.load.controller');
var _           = require ('lodash');
var routes = require ('../../../core/server/controllers/core.routes.controller');
var policy = require ('../../../core/server/controllers/core.policy.controller');

module.exports = function (app) {
	routes.setCRUDRoutes (app, 'project', Project, policy);
	//
	// add a phase to a project (from base phase)
	//
	app.route ('/api/project/:project/add/phase/:phaseBaseCode')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.addPhaseWithId (req.params.project, req.params.phaseBaseCode);
		}));
	// remove a phase from a project
	app.route ('/api/project/:project/remove/phase/:phase')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.removePhase (req.params.project, req.params.phase);
		}));
	//
	// start phase
	//
	app.route ('/api/project/:project/start/next/phase')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.startNextPhase (req.params.project);
		}));
	//
	// complete phase
	//
	app.route ('/api/project/:project/complete/phase/:phase')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.completePhase (req.params.project, req.params.phase);
		}));
	//
	// uncomplete phase
	//
	app.route ('/api/project/:project/uncomplete/phase/:phase')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.uncompletePhase (req.params.project, req.params.phase);
		}));
	//
	// get all projects in certain statuses
	//
	app.route ('/api/projects/with/status/:statustoken')
		.all (policy ('user'))
		.get (routes.setAndRun (Project, function (model, req) {
			var opts = {
				initiated      : 'Initiated',
				submitted      : 'Submitted',
				inprogress     : 'In Progress',
				certified      : 'Certified',
				decommissioned : 'Decommissioned'
			};
			var stat = opts[req.params.statustoken] || 'none';
			return model.list ({
				status : stat
			});
		}));
	//
	// publish or unpublish a project
	//
	app.route ('/api/project/:project/publish')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.publish (req.Project, true);
		}));
	app.route ('/api/project/:project/unpublish')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.publish (req.Project, false);
		}));
	app.route ('/api/project/:project/submit')
		.all (policy ('user'))
		.put (routes.setAndRun (Project, function (model, req) {
			return model.submit (req.Project);
		}));
	app.route ('/api/project/bycode/:projectcode')
		.all (policy ('guest'))
		.get (routes.setAndRun (Project, function (model, req) {
			return model.one ({code:req.params.projectcode});
		}));
	// app.route ('/api/')
	// 	.all (policy ('user'))
	// 	.get (function (req, res) {
	// 	var p = new Project (req.user);
	// 	p.list ().then (routes.success(res), routes.failure(res));
	// });

	app.route ('/api/projects/published')
		.get (routes.setAndRun (Project, function (model, req) {
			return model.published ();
		}));

	app.route ('/api/projects/mine')
		.get (routes.setAndRun (Project, function (model, req) {
			return model.mine ();
		}));

	app.route ('/api/projects/lookup')
		.all (policy ('guest'))
		.get (routes.setAndRun (Project, function (model, req) {
			return model.list ({},{_id: 1, code: 1, name: 1, region: 1, status: 1, memPermitID: 1})
			.then ( function(res) {
				var obj = {};
				_.each( res, function(item) {
					obj[item._id] = item;
				});
				return obj;
			});
		}));

	app.route ('/api/projects/regions')
		.all (policy ('user'))
		.get (routes.setAndRun (Project, function (model, req) {
			return model.list ({},{region: 1})
			.then ( function(res) {
				var obj = {};
				_.each( res, function(item) {
					obj[item.region] = item.region;
				});
				return obj;
			});
		}));

	app.route ('/api/projects/import/eao')
		.all (policy ('user'))
		.post (function (req, res) {
			var file = req.files.file;
			if (file) {
				// console.log("Received contact import file:",file);
				routes.setSessionContext(req)
				.then( function (opts) {
					// console.log("opts generated.");
					return projectLoad (file, req, res, opts);
				})
				.then (function (data) {
					// console.log("finished");
					res.json (data);
				});
			}
		});
	app.route ('/api/projects/import/mem')
		.all (policy ('user'))
		.post (function (req, res) {
			var file = req.files.file;
			if (file) {
				// console.log("Received contact import file:",file);
				routes.setSessionContext(req)
				.then( function (opts) {
					// console.log("opts generated.");
					return projectLoad (file, req, res, opts);
				})
				.then (function (data) {
					// console.log("finished");
					res.json (data);
				});
			}
		});
};

<|endoftext|>