<commit_before>/* Copyright (c) 2014 Jason Ish
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict';

(function() {

    angular.module("app").controller("AlertsController",
        AlertsController);

    function AlertsController($scope, EventRepository, $routeParams,
                              $location, baseUrl, Mousetrap, Util, $timeout, NotificationService) {

        var vm = this;
        vm.$routeParams = $routeParams;
        vm.activeRowIndex = 0;
        vm.openEventIndex = -1;
        vm.baseUrl = baseUrl;
        if (!$routeParams.page) {
            $routeParams.page = 1;
        }
        else {
            $routeParams.page = parseInt($routeParams.page);
        }

        /* Set to true when loading/refreshing.  False otherwise.
         * Used to update the UI when loading. */
        vm.loading = true;

        var sortByTimestamp = function(desc) {
            vm.events = _.sortBy(vm.events, function(event) {
                return event.timestamp;
            });
            if (desc) {
                vm.events.reverse();
            }
        };

        vm.selectAll = function() {
            _.forEach(vm.events, function(event) {
                event.selected = true;
            });
        };

        vm.deselectAll = function() {
            _.forEach(vm.events, function(event) {
                event.selected = false;
            });
        };

        var selectBySeverity = function(severity) {
            _.forEach(vm.events, function(event) {
                if (event._source.alert.severity == severity) {
                    event.selected = true;
                }
            })
        };
        vm.selectBySeverity = selectBySeverity;

        vm.gotoView = function(view) {
            $location.path(baseUrl + "/" + view);
        };

        vm.gotoPage = function(page) {
            $location.search({page: page});
        };

        vm.openEvent = function(event) {
            var index = _.indexOf(vm.events, event);
            if (vm.openEventIndex == index) {
                vm.openEventIndex = -1;
            }
            else {
                vm.openEventIndex = index;
                vm.activeRowIndex = index;

                /* XXX Scrolls the open event to the top. */
                $timeout(function() {
                    var element = $("table[event-table] tbody")
                        .eq(vm.openEventIndex);
                    $("html, body").animate(
                        {scrollTop: element.offset().top}, 100);

                });
            }
        };

        vm.openGroup = function(event) {
            var query = Util.printf(
                '{} +alert.signature.raw:"{}"',
                ($location.search().q || ""),
                event._source.alert.signature);
            $location.path(baseUrl + "/flat");
            $location.search({q: query.trim()});
        };

        vm.open = function(event) {
            if (event.count === undefined) {
                vm.openEvent(event);
            }
            else {
                vm.openGroup(event);
            }
        };

        vm.submitSearchForm = function() {
            $location.search({q: $routeParams.q});
        };

        vm.refresh = function() {
            load();
        };

        /**
         * Toggle the selected state of an event.
         */
        var toggleSelect = function(event) {
            if (event === undefined) {
                event = vm.events[vm.activeRowIndex];
            }
            event.selected = !event.selected;
        };

        /**
         * Remove an event from the event list, updating the activeRowIndex
         * if required.
         */
        var removeEvent = function(event) {
            var index = _.indexOf(vm.events, event);
            if (index == vm.openEventIndex) {
                vm.openEventIndex = -1;
            }
            if (vm.activeRowIndex > index) {
                vm.activeRowIndex--;
            }
            else if (vm.activeRowIndex == vm.events.length - 1) {
                vm.activeRowIndex--;
            }
            _.remove(vm.events, event);

            // Update the total event count in the result object.
            vm.result.total -= event.count || 1;

            if (vm.events.length == 0) {
                vm.refresh();
            }
        };

        var archiveGroup = function(selected) {
            _.forEach(selected, function(group) {
                group.archiving = true;

                var filters = _.cloneDeep(vm.filters);

                for (var key in group.keys) {
                    var filter = {term: {}};
                    filter.term[key] = group.keys[key];
                    filters.push(filter);
                }

                EventRepository.archiveByQuery({
                    query: $routeParams.q,
                    filters: filters,
                    lteTimestamp: group.timestamp
                }).then(function() {
                    removeEvent(group);
                }, function(error) {
                    NotificationService.add("danger", error);
                });
            });
        };

        /**
         * Recursively delete each event group, use selected as a stack as too
         * many simultaneous delete requests can result in ES returning an
         * error.
         */
        var deleteGroup = function(selected) {

            if (selected.length == 0) {
                return;
            }

            var group = selected.pop();
            var filters = _.cloneDeep(vm.filters);
            for (var key in group.keys) {
                var filter = {term: {}};
                filter.term[key] = group.keys[key];
                filters.push(filter);
            }

            EventRepository.deleteByQuery({
                query: $routeParams.q,
                filters: filters,
                lteTimestamp: group.timestamp
            }).then(function() {
                removeEvent(group);
                deleteGroup(selected);
            })
        };

        vm.getSelected = function() {
            return _.filter(vm.events, "selected");
        };

        vm.archiveSelected = function() {
            var selected = vm.getSelected();
            if (selected.length == 0) {
                return;
            }
            if (selected[0].count) {
                archiveGroup(selected);
            }
            else {
                _.forEach(selected, function(event) {
                    event.archiving = true;
                    EventRepository.archiveEvent(event)
                        .then(
                        function(result) {
                            removeEvent(event);
                        });
                });
            }
        };

        vm.deleteSelected = function() {
            var selected = vm.getSelected();
            if (selected.length == 0) {
                return;
            }

            _.forEach(selected, function(event) {
                event.deleting = true;
            });

            if (selected[0].count) {
                deleteGroup(selected);
            }
            else {
                _.forEach(selected, function(event) {
                    EventRepository.deleteEvent(event).then(
                        function(result) {
                            removeEvent(event);
                        }
                    );
                });
            }
        };

        var load = function() {

            vm.loading = true;
            vm.activeRowIndex = 0;

            if ($routeParams.view == "flat") {
                EventRepository.getEvents({
                    filters: vm.filters,
                    query: $routeParams.q,
                    page: $routeParams.page
                }).then(
                    function(result) {
                        vm.result = result;
                        vm.events = result.events;
                        vm.loading = false;
                    },
                    function(result) {
                        NotificationService.add("danger",
                            Util.printf("Error: {}",
                                result.statusText));
                        console.log("error:");
                        console.log(result);
                    }
                );
            }
            else if ($routeParams.view == "signature") {
                EventRepository.getAlertsGroupedBySignature({
                    filters: vm.filters,
                    query: $routeParams.q
                }).then(
                    function(result) {
                        vm.result = result;
                        vm.events = result.events;
                        sortByTimestamp(true);
                        vm.loading = false;
                    },
                    function(result) {
                        NotificationService.add("danger",
                            Util.printf("Error: {}",
                                result.statusText));
                        console.log("error:");
                        console.log(result);
                    }
                );
            }
            else if ($routeParams.view == "signature+src") {
                EventRepository.getAlertsGroupedBySignatureAndSource({
                    filters: vm.filters,
                    query: $routeParams.q
                }).then(
                    function(result) {
                        vm.result = result;
                        vm.events = result.events;
                        sortByTimestamp(true);
                        vm.loading = false;
                    },
                    function(result) {
                        NotificationService.add("danger",
                            Util.printf("Error: {}",
                                result.statusText));
                        console.log("error:");
                        console.log(result);
                    }
                );
            }

        };

        var getActiveEvent = function() {
            return vm.events[vm.activeRowIndex];
        };

        vm.toggleStar = function(event) {
            if (!event.count) {
                EventRepository.toggleStar(event);
            }
        };

        // Init.
        (function() {

            Mousetrap.bind($scope, "r", vm.refresh, "Refresh");
            Mousetrap.bind($scope, "* a", vm.selectAll, "Select All");
            Mousetrap.bind($scope, "* n", vm.deselectAll, "Deselect All");
            Mousetrap.bind($scope, "* 1", function() {
                selectBySeverity(1);
            }, "Select All Severity 1 Events");
            Mousetrap.bind($scope, "* 2", function() {
                selectBySeverity(2);
            }, "Select All Severity 2 Events");
            Mousetrap.bind($scope, "* 3", function() {
                selectBySeverity(3);
            }, "Select All Severity 3 Events");
            Mousetrap.bind($scope, "e", vm.archiveSelected,
                "Archive Selected Events");
            Mousetrap.bind($scope, "#", vm.deleteSelected,
                "Delete Selected Events");
            Mousetrap.bind($scope, "x", function() {
                toggleSelect();
            }, "Select Event");
            Mousetrap.bind($scope, "s", function() {
                vm.toggleStar(getActiveEvent());
            }, "Toggle 'Star'");
            Mousetrap.bind($scope, "/", function(e) {
                e.preventDefault();
                $("#search-form-input").focus();
                $("#search-form-input").select();
            }, "Search");
            Mousetrap.bind($scope, "g 1", function() {
                vm.gotoView("flat");
            }, "Go to Flat View");
            Mousetrap.bind($scope, "g 2", function() {
                vm.gotoView("signature");
            }, "Go to Grouped by Signature View");
            Mousetrap.bind($scope, "g 3", function() {
                vm.gotoView("signature+src");
            }, "Go to Grouped by Signature/Source View");
            Mousetrap.bind($scope, "o", function() {
                vm.open(getActiveEvent());
            }, "Open Event");

            vm.filters = [{term: {event_type: "alert"}}];

            if (baseUrl == "/inbox") {
                vm.filters.push({term: {tags: "inbox"}});
            }
            else if (baseUrl == "/starred") {
                vm.filters.push({term: {tags: "starred"}});
            }

            load();

        })();

    }
    ;

})();

<commit_msg>Send one archive by query request at a time.<commit_after>/* Copyright (c) 2014 Jason Ish
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict';

(function() {

    angular.module("app").controller("AlertsController",
        AlertsController);

    function AlertsController($scope, EventRepository, $routeParams,
                              $location, baseUrl, Mousetrap, Util, $timeout, NotificationService) {

        var vm = this;
        vm.$routeParams = $routeParams;
        vm.activeRowIndex = 0;
        vm.openEventIndex = -1;
        vm.baseUrl = baseUrl;
        if (!$routeParams.page) {
            $routeParams.page = 1;
        }
        else {
            $routeParams.page = parseInt($routeParams.page);
        }

        /* Set to true when loading/refreshing.  False otherwise.
         * Used to update the UI when loading. */
        vm.loading = true;

        var sortByTimestamp = function(desc) {
            vm.events = _.sortBy(vm.events, function(event) {
                return event.timestamp;
            });
            if (desc) {
                vm.events.reverse();
            }
        };

        vm.selectAll = function() {
            _.forEach(vm.events, function(event) {
                event.selected = true;
            });
        };

        vm.deselectAll = function() {
            _.forEach(vm.events, function(event) {
                event.selected = false;
            });
        };

        var selectBySeverity = function(severity) {
            _.forEach(vm.events, function(event) {
                if (event._source.alert.severity == severity) {
                    event.selected = true;
                }
            })
        };
        vm.selectBySeverity = selectBySeverity;

        vm.gotoView = function(view) {
            $location.path(baseUrl + "/" + view);
        };

        vm.gotoPage = function(page) {
            $location.search({page: page});
        };

        vm.openEvent = function(event) {
            var index = _.indexOf(vm.events, event);
            if (vm.openEventIndex == index) {
                vm.openEventIndex = -1;
            }
            else {
                vm.openEventIndex = index;
                vm.activeRowIndex = index;

                /* XXX Scrolls the open event to the top. */
                $timeout(function() {
                    var element = $("table[event-table] tbody")
                        .eq(vm.openEventIndex);
                    $("html, body").animate(
                        {scrollTop: element.offset().top}, 100);

                });
            }
        };

        vm.openGroup = function(event) {
            var query = Util.printf(
                '{} +alert.signature.raw:"{}"',
                ($location.search().q || ""),
                event._source.alert.signature);
            $location.path(baseUrl + "/flat");
            $location.search({q: query.trim()});
        };

        vm.open = function(event) {
            if (event.count === undefined) {
                vm.openEvent(event);
            }
            else {
                vm.openGroup(event);
            }
        };

        vm.submitSearchForm = function() {
            $location.search({q: $routeParams.q});
        };

        vm.refresh = function() {
            load();
        };

        /**
         * Toggle the selected state of an event.
         */
        var toggleSelect = function(event) {
            if (event === undefined) {
                event = vm.events[vm.activeRowIndex];
            }
            event.selected = !event.selected;
        };

        /**
         * Remove an event from the event list, updating the activeRowIndex
         * if required.
         */
        var removeEvent = function(event) {
            var index = _.indexOf(vm.events, event);
            if (index == vm.openEventIndex) {
                vm.openEventIndex = -1;
            }
            if (vm.activeRowIndex > index) {
                vm.activeRowIndex--;
            }
            else if (vm.activeRowIndex == vm.events.length - 1) {
                vm.activeRowIndex--;
            }
            _.remove(vm.events, event);

            // Update the total event count in the result object.
            vm.result.total -= event.count || 1;

            if (vm.events.length == 0) {
                vm.refresh();
            }
        };

        var archiveGroup = function(selected) {
            if (selected.length == 0) {
                return;
            }

            var group = selected.pop();
            var filters = _.cloneDeep(vm.filters);
            for (var key in group.keys) {
                var filter = {term: {}};
                filter.term[key] = group.keys[key];
                filters.push(filter);
            }

            EventRepository.archiveByQuery({
                query: $routeParams.q,
                filters: filters,
                lteTimestamp: group.timestamp
            }).then(function() {
                removeEvent(group);
                archiveGroup(selected);
            }, function(error) {
                NotificationService.add("danger", error);
            });
        };

        /**
         * Recursively delete each event group, use selected as a stack as too
         * many simultaneous delete requests can result in ES returning an
         * error.
         */
        var deleteGroup = function(selected) {
            if (selected.length == 0) {
                return;
            }

            var group = selected.pop();
            var filters = _.cloneDeep(vm.filters);
            for (var key in group.keys) {
                var filter = {term: {}};
                filter.term[key] = group.keys[key];
                filters.push(filter);
            }

            EventRepository.deleteByQuery({
                query: $routeParams.q,
                filters: filters,
                lteTimestamp: group.timestamp
            }).then(function() {
                removeEvent(group);
                deleteGroup(selected);
            })
        };

        vm.getSelected = function() {
            return _.filter(vm.events, "selected");
        };

        vm.archiveSelected = function() {
            var selected = vm.getSelected();
            if (selected.length == 0) {
                return;
            }
            if (selected[0].count) {
                archiveGroup(selected);
            }
            else {
                _.forEach(selected, function(event) {
                    event.archiving = true;
                    EventRepository.archiveEvent(event)
                        .then(
                        function(result) {
                            removeEvent(event);
                        });
                });
            }
        };

        vm.deleteSelected = function() {
            var selected = vm.getSelected();
            if (selected.length == 0) {
                return;
            }

            _.forEach(selected, function(event) {
                event.deleting = true;
            });

            if (selected[0].count) {
                deleteGroup(selected);
            }
            else {
                _.forEach(selected, function(event) {
                    EventRepository.deleteEvent(event).then(
                        function(result) {
                            removeEvent(event);
                        }
                    );
                });
            }
        };

        var load = function() {

            vm.loading = true;
            vm.activeRowIndex = 0;

            if ($routeParams.view == "flat") {
                EventRepository.getEvents({
                    filters: vm.filters,
                    query: $routeParams.q,
                    page: $routeParams.page
                }).then(
                    function(result) {
                        vm.result = result;
                        vm.events = result.events;
                        vm.loading = false;
                    },
                    function(result) {
                        NotificationService.add("danger",
                            Util.printf("Error: {}",
                                result.statusText));
                        console.log("error:");
                        console.log(result);
                    }
                );
            }
            else if ($routeParams.view == "signature") {
                EventRepository.getAlertsGroupedBySignature({
                    filters: vm.filters,
                    query: $routeParams.q
                }).then(
                    function(result) {
                        vm.result = result;
                        vm.events = result.events;
                        sortByTimestamp(true);
                        vm.loading = false;
                    },
                    function(result) {
                        NotificationService.add("danger",
                            Util.printf("Error: {}",
                                result.statusText));
                        console.log("error:");
                        console.log(result);
                    }
                );
            }
            else if ($routeParams.view == "signature+src") {
                EventRepository.getAlertsGroupedBySignatureAndSource({
                    filters: vm.filters,
                    query: $routeParams.q
                }).then(
                    function(result) {
                        vm.result = result;
                        vm.events = result.events;
                        sortByTimestamp(true);
                        vm.loading = false;
                    },
                    function(result) {
                        NotificationService.add("danger",
                            Util.printf("Error: {}",
                                result.statusText));
                        console.log("error:");
                        console.log(result);
                    }
                );
            }

        };

        var getActiveEvent = function() {
            return vm.events[vm.activeRowIndex];
        };

        vm.toggleStar = function(event) {
            if (!event.count) {
                EventRepository.toggleStar(event);
            }
        };

        // Init.
        (function() {

            Mousetrap.bind($scope, "r", vm.refresh, "Refresh");
            Mousetrap.bind($scope, "* a", vm.selectAll, "Select All");
            Mousetrap.bind($scope, "* n", vm.deselectAll, "Deselect All");
            Mousetrap.bind($scope, "* 1", function() {
                selectBySeverity(1);
            }, "Select All Severity 1 Events");
            Mousetrap.bind($scope, "* 2", function() {
                selectBySeverity(2);
            }, "Select All Severity 2 Events");
            Mousetrap.bind($scope, "* 3", function() {
                selectBySeverity(3);
            }, "Select All Severity 3 Events");
            Mousetrap.bind($scope, "e", vm.archiveSelected,
                "Archive Selected Events");
            Mousetrap.bind($scope, "#", vm.deleteSelected,
                "Delete Selected Events");
            Mousetrap.bind($scope, "x", function() {
                toggleSelect();
            }, "Select Event");
            Mousetrap.bind($scope, "s", function() {
                vm.toggleStar(getActiveEvent());
            }, "Toggle 'Star'");
            Mousetrap.bind($scope, "/", function(e) {
                e.preventDefault();
                $("#search-form-input").focus();
                $("#search-form-input").select();
            }, "Search");
            Mousetrap.bind($scope, "g 1", function() {
                vm.gotoView("flat");
            }, "Go to Flat View");
            Mousetrap.bind($scope, "g 2", function() {
                vm.gotoView("signature");
            }, "Go to Grouped by Signature View");
            Mousetrap.bind($scope, "g 3", function() {
                vm.gotoView("signature+src");
            }, "Go to Grouped by Signature/Source View");
            Mousetrap.bind($scope, "o", function() {
                vm.open(getActiveEvent());
            }, "Open Event");

            vm.filters = [{term: {event_type: "alert"}}];

            if (baseUrl == "/inbox") {
                vm.filters.push({term: {tags: "inbox"}});
            }
            else if (baseUrl == "/starred") {
                vm.filters.push({term: {tags: "starred"}});
            }

            load();

        })();

    }
    ;

})();

<|endoftext|>


<commit_before>/*global define*/
define(
	[ 'aux/canvas', 'aux/collection' ],
	function( canvas_helper, collection_helper )
	{
		var signals;
		var element;
		var ctx;
		var points = [ ];
		var is_pressed;
		var closest_point;
		var is_over = false;
		var current_pos = { x: 0, y: 0 };
		var last_pos = current_pos;
		var grid_size = 50;

		function init( shared )
		{
			signals = shared.signals;
			element = document.getElementById( 'grid-canvas' );
			ctx     = element.getContext( '2d' );

			resetPoints();
			addListeners();

			signals['control-updated'].add( controlsUpdated );
			signals['image-loaded'].add( resizeCanvas );
			signals['image-loaded'].add( resetPoints );
			signals['image-loaded'].add( update );

		}

		function addListeners()
		{
			element.addEventListener( 'mousedown', mousePressed );
			element.addEventListener( 'mousemove', mouseMoved );
			element.addEventListener( 'mouseup', mouseReleased );
			element.addEventListener( 'mouseout', mouseOuted );
			element.addEventListener( 'mouseover', mouseHovered );
		}

		function controlsUpdated( new_values )
		{
			if ( new_values.grid_size !== grid_size )
			{
				grid_size = parseInt( new_values.grid_size, 10 );
				resetPoints();
				update();
			}
		}

		function mousePressed( event )
		{
			is_pressed = true;

			updateMousePosition( event.offsetX, event.offsetY );
		}

		function mouseReleased( event )
		{
			is_pressed = false;

			updateMousePosition( event.offsetX, event.offsetY );
		}

		function mouseMoved( event )
		{
			updateMousePosition( event.offsetX, event.offsetY );
		}

		function mouseHovered( event )
		{
			is_over = true;
		}

		function mouseOuted()
		{
			is_over = false;
			is_pressed = false;
			update();
		}

		function updateMousePosition( x, y )
		{
			last_pos = current_pos;

			current_pos.x = x;
			current_pos.y = y;

			update();
		}

		function update()
		{
			closest_point = getClosestPoint( points, current_pos );

			if ( is_over && is_pressed )
			{
				closest_point.x_end = current_pos.x;
				closest_point.y_end = current_pos.y;

				signals['points-updated'].dispatch( points );
			}

			ctx.clearRect( 0, 0, element.width, element.height );

			drawGrid( ctx, points );

			if ( closest_point && is_over )
			{
				ctx.beginPath();
				ctx.fillStyle = '#0066ff';
				ctx.lineWidth = 3;
				ctx.strokeStyle = '#cccccc';
				ctx.arc( closest_point.x_end, closest_point.y_end, 4, 0, Math.PI * 2, true );
				ctx.stroke();
				ctx.fill();
				ctx.closePath();
			}
		}

		function drawGrid( ctx, points )
		{
			var p1, p2, p3, p4;

			for ( var i = 0; i < points.length; i++ )
			{
				p1 = points[i];
				p2 = collection_helper.getItemByValue( points, 'row', p1.row + 1, 'column', p1.column );
				p3 = collection_helper.getItemByValue( points, 'row', p1.row,     'column', p1.column + 1 );
				p4 = collection_helper.getItemByValue( points, 'row', p1.row + 1, 'column', p1.column + 1 );

				if ( p1 && p2 && p3 && p4 )
				{
					ctx.beginPath();
					ctx.moveTo( p1.x_end, p1.y_end );
					ctx.lineTo( p3.x_end, p3.y_end );
					ctx.lineTo( p4.x_end, p4.y_end );
					ctx.lineTo( p2.x_end, p2.y_end );
					ctx.lineTo( p1.x_end, p1.y_end );

					if ( is_over )
					{
						ctx.lineWidth = 0.4;
					}

					else
					{
						ctx.lineWidth = 0.1;
					}

					ctx.strokeStyle = '#000000';
					ctx.stroke();
					ctx.closePath();
				}
			}
		}

		function resizeCanvas( image )
		{
			canvas_helper.resize( element, image );
		}

		function resetPoints()
		{
			points = getPoints();
			signals['points-updated'].dispatch( points );
		}

		function getPoints()
		{
			var result = [ ];
			var column = 0;
			var row = 0;
			var index = 0;
			var x = 0;
			var y = 0;
			var width = element.width;
			var height = element.height;

			for ( x = 0; x < width; x += grid_size )
			{
				row = 0;

				for ( y = 0; y < height; y += grid_size )
				{
					result[index] = { x: x, y: y, x_end:x, y_end: y, column: column, row: row, index: index };
					index++;
					row++;
				}

				column++;
			}

			return result;
		}

		function getClosestPoint( points, pos )
		{
			var i = 0;
			var len = points.length;
			var shortest_distance = Infinity;
			var distance = Infinity;
			var result;

			for ( i = 0; i < len; i++ )
			{
				distance = getDistance( { x: points[i].x_end, y: points[i].y_end }, pos );

				if ( distance < shortest_distance )
				{
					shortest_distance = distance;
					result = points[i];
				}
			}

			return result;
		}

		function getDistance( p1, p2 )
		{
			var xs = 0;
			var ys = 0;

			xs = p2.x - p1.x;
			xs = xs * xs;

			ys = p2.y - p1.y;
			ys = ys * ys;

			return Math.sqrt( xs + ys );
		}

		return { init: init };
	}
);<commit_msg>add spec compliance / firefox compatibility<commit_after>/*global define*/
define(
	[ 'aux/canvas', 'aux/collection' ],
	function( canvas_helper, collection_helper )
	{
		var signals;
		var element;
		var ctx;
		var points = [ ];
		var is_pressed;
		var closest_point;
		var is_over = false;
		var current_pos = { x: 0, y: 0 };
		var last_pos = current_pos;
		var grid_size = 50;

		function init( shared )
		{
			signals = shared.signals;
			element = document.getElementById( 'grid-canvas' );
			ctx     = element.getContext( '2d' );

			resetPoints();
			addListeners();

			signals['control-updated'].add( controlsUpdated );
			signals['image-loaded'].add( resizeCanvas );
			signals['image-loaded'].add( resetPoints );
			signals['image-loaded'].add( update );

		}

		function addListeners()
		{
			element.addEventListener( 'mousedown', mousePressed );
			element.addEventListener( 'mousemove', mouseMoved );
			element.addEventListener( 'mouseup', mouseReleased );
			element.addEventListener( 'mouseout', mouseOuted );
			element.addEventListener( 'mouseover', mouseHovered );
		}

		function controlsUpdated( new_values )
		{
			if ( new_values.grid_size !== grid_size )
			{
				grid_size = parseInt( new_values.grid_size, 10 );
				resetPoints();
				update();
			}
		}

		function mousePressed( event )
		{
			is_pressed = true;

			updateMousePosition( event );
		}

		function mouseReleased( event )
		{
			is_pressed = false;

			updateMousePosition( event );
		}

		function mouseMoved( event )
		{
			updateMousePosition( event );
		}

		function mouseHovered( event )
		{
			is_over = true;
		}

		function mouseOuted()
		{
			is_over = false;
			is_pressed = false;
			update();
		}

		function updateMousePosition( event )
		{
			last_pos = current_pos;

			if (
				typeof event.offsetX !== 'undefined' &&
				typeof event.offsetY !== 'undefined'
			)
			{
				current_pos.x = event.offsetX;
				current_pos.y = event.offsetY;
			}

			else
			{
				current_pos.x = event.layerX;
				current_pos.y = event.layerY;
			}

			update();
		}

		function update()
		{
			closest_point = getClosestPoint( points, current_pos );

			if (
				is_over &&
				is_pressed
			)
			{
				closest_point.x_end = current_pos.x;
				closest_point.y_end = current_pos.y;

				signals['points-updated'].dispatch( points );
			}

			ctx.clearRect( 0, 0, element.width, element.height );

			drawGrid( ctx, points );

			if ( closest_point && is_over )
			{
				ctx.beginPath();
				ctx.fillStyle = '#0066ff';
				ctx.lineWidth = 3;
				ctx.strokeStyle = '#cccccc';
				ctx.arc( closest_point.x_end, closest_point.y_end, 4, 0, Math.PI * 2, true );
				ctx.stroke();
				ctx.fill();
				ctx.closePath();
			}
		}

		function drawGrid( ctx, points )
		{
			var p1, p2, p3, p4;

			for ( var i = 0; i < points.length; i++ )
			{
				p1 = points[i];
				p2 = collection_helper.getItemByValue( points, 'row', p1.row + 1, 'column', p1.column );
				p3 = collection_helper.getItemByValue( points, 'row', p1.row,     'column', p1.column + 1 );
				p4 = collection_helper.getItemByValue( points, 'row', p1.row + 1, 'column', p1.column + 1 );

				if ( p1 && p2 && p3 && p4 )
				{
					ctx.beginPath();
					ctx.moveTo( p1.x_end, p1.y_end );
					ctx.lineTo( p3.x_end, p3.y_end );
					ctx.lineTo( p4.x_end, p4.y_end );
					ctx.lineTo( p2.x_end, p2.y_end );
					ctx.lineTo( p1.x_end, p1.y_end );

					if ( is_over )
					{
						ctx.lineWidth = 0.4;
					}

					else
					{
						ctx.lineWidth = 0.1;
					}

					ctx.strokeStyle = '#000000';
					ctx.stroke();
					ctx.closePath();
				}
			}
		}

		function resizeCanvas( image )
		{
			canvas_helper.resize( element, image );
		}

		function resetPoints()
		{
			points = getPoints();
			signals['points-updated'].dispatch( points );
		}

		function getPoints()
		{
			var result = [ ];
			var column = 0;
			var row = 0;
			var index = 0;
			var x = 0;
			var y = 0;
			var width = element.width;
			var height = element.height;

			for ( x = 0; x < width; x += grid_size )
			{
				row = 0;

				for ( y = 0; y < height; y += grid_size )
				{
					result[index] = { x: x, y: y, x_end:x, y_end: y, column: column, row: row, index: index };
					index++;
					row++;
				}

				column++;
			}

			return result;
		}

		function getClosestPoint( points, pos )
		{
			var i = 0;
			var len = points.length;
			var shortest_distance = Infinity;
			var distance = Infinity;
			var result;

			for ( i = 0; i < len; i++ )
			{
				distance = getDistance( { x: points[i].x_end, y: points[i].y_end }, pos );

				if ( distance < shortest_distance )
				{
					shortest_distance = distance;
					result = points[i];
				}
			}

			return result;
		}

		function getDistance( p1, p2 )
		{
			var xs = 0;
			var ys = 0;

			xs = p2.x - p1.x;
			xs = xs * xs;

			ys = p2.y - p1.y;
			ys = ys * ys;

			return Math.sqrt( xs + ys );
		}

		return { init: init };
	}
);<|endoftext|>


<commit_before>import { COLOR, LENGTH } from "../../consts/types";

export default {
  "textLink.focus.haloColor": {
    type: COLOR,
    value: {
      ref: "colorScheme.halo.focus"
    }
  },
  "textLink.focus.haloWidth": {
    type: LENGTH,
    value: "2px"
  },
  "textLink.primary.default.fontColor": {
    type: COLOR,
    value: {
      ref: "basics.colors.textLink.primary.againstLight"
    }
  },
  "textLink.primary.hover.fontColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.default.fontColor"
    }
  },
  "textLink.primary.focus.fontColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.default.fontColor"
    }
  },
  "textLink.primary.hover.underlineColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.default.fontColor"
    }
  },
  "textLink.secondary.default.fontColor": {
    type: COLOR,
    value: {
      ref: "basics.colors.textLink.secondary.againstLight"
    }
  },
  "textLink.secondary.hover.fontColor": {
    type: COLOR,
    value: {
      ref: "basics.colors.textLink.secondary.againstLight"
    }
  },
  "textLink.secondary.focus.fontColor": {
    type: COLOR,
    value: {
      ref: "basics.colors.textLink.secondary.againstLight"
    }
  },
  "textLink.secondary.hover.underlineColor": {
    type: COLOR,
    value: {
      ref: "basics.colors.textLink.secondary.againstLight"
    }
  },
  /**
   * ## Deprecated
   *
   *
   */
  "textLink.textColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.default.fontColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.primary.default.fontColor"
      }
    }
  },
  "textLink.hover.textColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.hover.fontColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.primary.hover.fontColor"
      }
    }
  },
  "textLink.focus.textColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.focus.fontColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.primary.focus.fontColor"
      }
    }
  },
  "textLink.hover.underline.color": {
    type: COLOR,
    value: {
      ref: "textLink.primary.hover.underlineColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.primary.hover.underlineColor"
      }
    }
  },
  "textLink.focus.halo.color": {
    type: COLOR,
    value: {
      ref: "textLink.focus.haloColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.focus.haloColor"
      }
    }
  },
  "textLink.focus.halo.width": {
    type: LENGTH,
    value: {
      ref: "textLink.focus.haloWidth"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.focus.haloWidth"
      }
    }
  }
};
<commit_msg>refactor: changed secondary text link ref<commit_after>import { COLOR, LENGTH } from "../../consts/types";

export default {
  "textLink.focus.haloColor": {
    type: COLOR,
    value: {
      ref: "colorScheme.halo.focus"
    }
  },
  "textLink.focus.haloWidth": {
    type: LENGTH,
    value: "2px"
  },
  "textLink.primary.default.fontColor": {
    type: COLOR,
    value: {
      ref: "basics.colors.textLink.primary.againstLight"
    }
  },
  "textLink.primary.hover.fontColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.default.fontColor"
    }
  },
  "textLink.primary.focus.fontColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.default.fontColor"
    }
  },
  "textLink.primary.hover.underlineColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.default.fontColor"
    }
  },
  "textLink.secondary.default.fontColor": {
    type: COLOR,
    value: {
      ref: "colorScheme.text.default"
    }
  },
  "textLink.secondary.hover.fontColor": {
    type: COLOR,
    value: {
      ref: "colorScheme.text.default"
    }
  },
  "textLink.secondary.focus.fontColor": {
    type: COLOR,
    value: {
      ref: "colorScheme.text.default"
    }
  },
  "textLink.secondary.hover.underlineColor": {
    type: COLOR,
    value: {
      ref: "colorScheme.text.default"
    }
  },
  /**
   * ## Deprecated
   *
   *
   */
  "textLink.textColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.default.fontColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.primary.default.fontColor"
      }
    }
  },
  "textLink.hover.textColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.hover.fontColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.primary.hover.fontColor"
      }
    }
  },
  "textLink.focus.textColor": {
    type: COLOR,
    value: {
      ref: "textLink.primary.focus.fontColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.primary.focus.fontColor"
      }
    }
  },
  "textLink.hover.underline.color": {
    type: COLOR,
    value: {
      ref: "textLink.primary.hover.underlineColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.primary.hover.underlineColor"
      }
    }
  },
  "textLink.focus.halo.color": {
    type: COLOR,
    value: {
      ref: "textLink.focus.haloColor"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.focus.haloColor"
      }
    }
  },
  "textLink.focus.halo.width": {
    type: LENGTH,
    value: {
      ref: "textLink.focus.haloWidth"
    },
    metadata: {
      deprecated: {
        equivalent: "textLink.focus.haloWidth"
      }
    }
  }
};
<|endoftext|>


<commit_before>var path = require('path'); // File path processing. http://nodejs.org/api/path.html
var _ = require('underscore'); // Utilities. http://underscorejs.org/
var Backbone = require('backbone'); // Data model utilities. http://backbonejs.org/
var moment = require('moment'); // Date processing. http://momentjs.com/
var request = require('request'); // Simpler HTTP. https://github.com/mikeal/request
var progress = require('request-progress'); // Progress events on downloads. https://github.com/IndigoUnited/node-request-progress
var XRegExp = require('xregexp').XRegExp; // Fancy regular expressions. http://xregexp.com/
var rimraf = require('rimraf'); // Recursive directory delete. https://github.com/isaacs/rimraf
var fs = require('node-fs'); // Recursive directory creation. https://github.com/bpedro/node-fs
var ncp = require('ncp').ncp; // Recursive directory copy. https://npmjs.org/package/ncp

// Update content for the application, as well as the application itself.
exports.ContentUpdater = Backbone.Model.extend({

    defaults: {
        // When the content was last updated.
        updated: null,

        // The remote URL to the root XML.
        remote: null,

        // The final local path for content.
        local: '../content/',

        // The temp path for content.
        temp: '../content.tmp/',

        // A collection of file objects that are being processed.
        files: null
    },

    // A callback to call when updating is complete.
    _callback: null,

    // Manually update content.
    update: function(callback) {
        this._callback = callback;
        this._initDirectories(_.bind(function() {
            request(this.get('remote'), _.bind(this._processContentRoot, this));
        }, this));
    },

    // Set up the temp and output directories.
    _initDirectories: function(callback) {
        // Delete the temp directory.
        rimraf(this.get('temp'), _.bind(function(error) {
            this._handleError('Error clearing temp directory.', error);

            // Make the temp directory.
            fs.mkdir(this.get('temp'), 0777, true, _.bind(function(error) {
                this._handleError('Error creating temp directory.', error);

                fs.exists(this.get('local'), _.bind(function(exists) {
                    if (exists) {
                        callback();
                        return;
                    }

                    // Make the ouput directory.
                    fs.mkdir(this.get('local'), 0777, true, _.bind(function(error) {
                        this._handleError('Error creating ouput directory.', error);
                        callback();
                    }, this));
                }, this));
            }, this));
        }, this));
    },

    // Process the XML file to extract files to load.
    _processContentRoot: function(error, response, body) {
        this._handleError('Error loading root XML.', error);

        // Write the root XML file.
        fs.writeFile(this.get('temp') + 'content.xml', body, _.bind(function(error) {
            this._handleError('Error writing root XML.', error);
            this.set('files', new exports.ContentFiles());

            // Collect any URLs in root file.
            var pattern = new XRegExp(/>(http.*?)</gi);
            var matches = [];
            var match;

            while (true) {
                match = pattern.exec(body);
                if (!match) {
                    break;
                }
                matches.push(match);
            }

            // Figure out what each URL begins with -- this is removed to create the relative path.
            var prefix = '';

            function iterator(element, index, list) {
                return element[1].indexOf(prefix) === 0;
            }

            while (true) {
                prefix += matches[0][1][prefix.length];
                if (!_.every(matches, iterator)) {
                    prefix = prefix.substr(0, prefix.length - 1);
                    break;
                }
            }

            // Build file objects.
            _.each(matches, function(element, index, list) {
                var url = element[1];
                var relativePath = url.substr(prefix.length);
                var file = new exports.ContentFile({
                    url: url,
                    filePath: this.get('local') + relativePath,
                    tempPath: this.get('temp') + relativePath
                });

                file.on('loaded', this._onFileLoaded, this);
                this.get('files').add(file);
            }, this);

            _.each(this.get('files').models, _.bind(this._processFile, this));
        }, this));
    },

    // Determine if the file needs to be loaded, or if it's already up to date.
    _processFile: function(contentFile) {
        fs.exists(contentFile.get('filePath'), _.bind(function(exists) {
            if (!exists) {
                // The file doesn't exist locally, so download it.
                this._downloadFile(contentFile);
                return;
            }

            // The file does exist locally, check if the remote one is newer.
            fs.stat(contentFile.get('filePath'), _.bind(function(error, stats) {
                var localFileModified = moment(stats.mtime);
                request({
                    url: contentFile.get('url'),
                    method: 'HEAD'
                }, _.bind(function(error, response, body) {
                    var remoteFileModified = moment(response.headers['last-modified']);
                    if (remoteFileModified.isAfter(localFileModified)) {
                        // The remote file is newer, go get it.
                        this._downloadFile(contentFile);
                        return;
                    }

                    // The local file is newer, flag it as loaded.
                    contentFile.set('progress', 1);
                }, this));
            }, this));
        }, this));
    },

    // Load the file into memory and create its temp output directory.
    _downloadFile: function(contentFile) {
        console.log('Downloading ' + contentFile.get('url'));

        // Request the file from the network.
        progress(request({
            url: contentFile.get('url'),
            encoding: null // Required for binary files.
        }, _.bind(function(error, response, body) {
            this._handleError('Error loading ' + contentFile.get('url'), error);

            // Create the file's output directory if needed.
            var dir = path.dirname(contentFile.get('tempPath'));
            fs.exists(dir, _.bind(function(exists) {
                if (!exists) {
                    fs.mkdir(dir, 0777, true, _.bind(function(error) {
                        this._handleError('Error creating temp directory for file.', error);
                        this._writeFile(contentFile, body);
                    }, this));
                } else {
                    this._writeFile(contentFile, body);
                }
            }, this));

        }, this))).on('progress', function(state) {

            // Set progress properties on the file.
            contentFile.set('receivedBytes', state.received);
            contentFile.set('totalBytes', state.total);
            contentFile.set('progress', state.percent / 100);
        });
    },

    // When the file is done loading, write it to disk.
    _writeFile: function(contentFile, body) {
        fs.writeFile(contentFile.get('tempPath'), body, null, _.bind(function(error) {
            this._handleError('Error writing file.', error);
            contentFile.set('progress', 1);
        }, this));
    },

    // Called when the progress of a file is set to 1.
    _onFileLoaded: function(contentFile) {
        contentFile.off('loaded', this._onFileLoaded, this);

        // Determine if all files are loaded.
        var filesToGo = _.filter(this.get('files').models, function(file) {
            return file.get('progress') < 1;
        }).length;
        var style = contentFile.get('totalBytes') ? 'loaded' : 'cached';
        console.log(contentFile.get('url') + ' ' + style + ', ' + filesToGo + ' to go');

        if (!filesToGo) {
            this._processFiles();
        }
    },

    // Copy files to their final destination when all files are loaded.
    // TODO: If a file is removed from the CMS, it will never get removed from the output directory.
    _processFiles: function() {
        // Recursive copy from temp to target.
        ncp(this.get('temp'), this.get('local'), _.bind(function(error) {
            this._handleError('Error copying from temp folder.', error);

            // Delete the temp folder.
            rimraf(this.get('temp'), _.bind(function(error) {
                this._handleError('Error clearing temp directory.', error);
                this._completed();
            }, this));
        }, this));
    },

    // Notify on completion.
    _completed: function() {
        this.set('updated', moment());
        this.trigger('complete');
        if (this._callback) {
            this._callback();
        }
    },

    // Generic error handling function.
    // TODO: Replace with real logging.
    _handleError: function(message, error) {
        if (!error) {
            return;
        }

        console.log(message);
        console.log(error);
        if (this._callback) {
            this._callback(error);
        }

        throw error;
    }
});

exports.ContentFile = Backbone.Model.extend({
    defaults: {
        url: null,
        filePath: null,
        tempPath: null,
        progress: 0,
        receivedBytes: 0,
        totalBytes: 0
    },

    initialize: function() {
        this.on('change:progress', function(model, value, options) {
            if (value >= 1) {
                this.trigger('loaded', this);
            }
        }, this);
    }
});

exports.ContentFiles = Backbone.Collection.extend({
    model: exports.ContentFile
});
<commit_msg>extra file<commit_after><|endoftext|>


<commit_before>/**
 * @author Hana Lee
 * @since 2016-04-23 20:36
 */

(function () {
  'use strict';

  angular.module('translate-chat').controller('FriendListCtrl', FriendListController);

  FriendListController.$inject = [
    '$scope', '$rootScope', '$ionicTabsDelegate', '$state', '$ionicHistory', '$ionicModal',
    'UserService', 'ChatService', 'SocketService', 'FriendService'
  ];
  function FriendListController($scope, $rootScope, $ionicTabsDelegate, $state, $ionicHistory, $ionicModal,
                                UserService, ChatService, SocketService, FriendService) {
    $scope.friends = [];
    $scope.users = [];

    console.log('friend controller');

    SocketService.on('addedFriend', function (data) {
      if (data.error) {
        console.error('added friend error : ', data);
      } else {
        UserService.createUserOnLocal(data.result).then(function () {
          FriendService.addToLocal($rootScope.user, data.result).then(function () {
            $scope.friends.push(data.result);
          }, function (error) {
            console.error('insert friend to local error : ', error);
          });
        }, function (error) {
          console.error('insert friend to local user table error : ', error);
        });
      }
    });

    $scope.remove = function (user) {
      console.log('remove user', user);
    };

    $ionicModal.fromTemplateUrl('app/views/friend-list/modal/user-list-modal.html', {
      scope : $scope,
      animation : 'slide-in-down'
    }).then(function (userListModal) {
      $scope.userListModal = userListModal;
    });

    $scope.showUsers = function () {
      UserService.getAllUserFromServer($rootScope.user).then(function (result) {
        $scope.users = result;
        $scope.userListModal.show();
      });
    };

    $scope.hideUserListModal = function () {
      $scope.userListModal.hide();
    };

    $scope.addFriend = function (friend) {
      UserService.createUserOnLocal(friend).then(function () {
        FriendService.add($rootScope.user, friend).then(function () {
          FriendService.getAll($rootScope.user).then(function (result) {
            $scope.friends = result;
            console.log('friends list', $scope.friends);
            $scope.userListModal.hide();
          });
        }, function (error) {
          console.error('insert friend error : ', error);
        });
      }, function (error) {
        console.error('insert friend to local user table error : ', error);
      });
    };

    $scope.$on('$ionicView.beforeEnter', function () {
      $ionicTabsDelegate.showBar(true);
    });

    function _initializeFriends(userData) {
      FriendService.getAll(userData).then(function (result) {
        $scope.friends = result;
      });
    }

    $scope.$on('$ionicView.enter', function () {
      if (!$rootScope.user.user_name) {
        $state.go('user-name');
      } else if ($scope.friends.length === 0) {
        _initializeFriends($rootScope.user);
      }
    });

    function joinChatRoom(chatRoomId, friend) {
      ChatService.join(chatRoomId, $rootScope.user, friend).then(function () {
        var viewId = $ionicHistory.viewHistory().currentView.viewId;
        $state.go('tab.chat-room', {chatRoomId : chatRoomId, backViewId : viewId});
      }, function (error) {
        console.log('joining chat room error : ', error);
      });
    }

    $scope.joinChatRoom = function (friend) {
      ChatService.getChatRoomIdByUserAndFriend($rootScope.user, friend).then(function (result) {
        console.log('get chat room id by user and friend result : ', result);
        joinChatRoom(result, friend);
      }, function (error) {
        console.error('get chat room id by user and friend error : ', error);

        ChatService.createRoom().then(function (createdChatRoomId) {
          joinChatRoom(createdChatRoomId, friend);
        }, function (error) {
          console.error('create chat room error : ', error);
        });
      });
    };
  }
})();
<commit_msg>* 다른 유저가 친구 추가를 했을때 동작하는 이벤트에서 친구 목록에 push 할때 null 오브젝트에 push 하려고 하여 오류 발생하는 문제 해결<commit_after>/**
 * @author Hana Lee
 * @since 2016-04-23 20:36
 */

(function () {
  'use strict';

  angular.module('translate-chat').controller('FriendListCtrl', FriendListController);

  FriendListController.$inject = [
    '$scope', '$rootScope', '$ionicTabsDelegate', '$state', '$ionicHistory', '$ionicModal',
    'UserService', 'ChatService', 'SocketService', 'FriendService'
  ];
  function FriendListController($scope, $rootScope, $ionicTabsDelegate, $state, $ionicHistory, $ionicModal,
                                UserService, ChatService, SocketService, FriendService) {
    $scope.friends = [];
    $scope.users = [];

    console.log('friend controller');

    SocketService.on('addedFriend', function (data) {
      if (data.error) {
        console.error('added friend error : ', data);
      } else {
        UserService.createUserOnLocal(data.result).then(function () {
          FriendService.addToLocal($rootScope.user, data.result).then(function () {
            if (!$scope.friends) {
              $scope.friends = [];
            }
            $scope.friends.push(data.result);
          }, function (error) {
            console.error('insert friend to local error : ', error);
          });
        }, function (error) {
          console.error('insert friend to local user table error : ', error);
        });
      }
    });

    $scope.remove = function (user) {
      console.log('remove user', user);
    };

    $ionicModal.fromTemplateUrl('app/views/friend-list/modal/user-list-modal.html', {
      scope : $scope,
      animation : 'slide-in-down'
    }).then(function (userListModal) {
      $scope.userListModal = userListModal;
    });

    $scope.showUsers = function () {
      UserService.getAllUserFromServer($rootScope.user).then(function (result) {
        $scope.users = result;
        $scope.userListModal.show();
      });
    };

    $scope.hideUserListModal = function () {
      $scope.userListModal.hide();
    };

    $scope.addFriend = function (friend) {
      UserService.createUserOnLocal(friend).then(function () {
        FriendService.add($rootScope.user, friend).then(function () {
          FriendService.getAll($rootScope.user).then(function (result) {
            $scope.friends = result;
            console.log('friends list', $scope.friends);
            $scope.userListModal.hide();
          });
        }, function (error) {
          console.error('insert friend error : ', error);
        });
      }, function (error) {
        console.error('insert friend to local user table error : ', error);
      });
    };

    $scope.$on('$ionicView.beforeEnter', function () {
      $ionicTabsDelegate.showBar(true);
    });

    function _initializeFriends(userData) {
      FriendService.getAll(userData).then(function (result) {
        $scope.friends = result;
      });
    }

    $scope.$on('$ionicView.enter', function () {
      if (!localStorage.getItem('translate-chat-user-name')) {
        $state.go('user-name');
      } else if ($scope.friends.length === 0) {
        _initializeFriends($rootScope.user);
      }
    });

    function joinChatRoom(chatRoomId, friend) {
      ChatService.join(chatRoomId, $rootScope.user, friend).then(function () {
        var viewId = $ionicHistory.viewHistory().currentView.viewId;
        $state.go('tab.chat-room', {chatRoomId : chatRoomId, backViewId : viewId});
      }, function (error) {
        console.log('joining chat room error : ', error);
      });
    }

    $scope.joinChatRoom = function (friend) {
      ChatService.getChatRoomIdByUserAndFriend($rootScope.user, friend).then(function (result) {
        console.log('get chat room id by user and friend result : ', result);
        joinChatRoom(result, friend);
      }, function (error) {
        console.error('get chat room id by user and friend error : ', error);

        ChatService.createRoom().then(function (createdChatRoomId) {
          joinChatRoom(createdChatRoomId, friend);
        }, function (error) {
          console.error('create chat room error : ', error);
        });
      });
    };
  }
})();
<|endoftext|>


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

'use strict';

// MODULES //

var isFunction = require( '@stdlib/assert/is-function' );
var isArrayLikeObject = require( '@stdlib/assert/is-array-like-object' );
var hasOwnProp = require( '@stdlib/assert/has-own-property' );

// MAIN //

/**
* Creates (or fills) an array from an iterator.
*
* @param {ArrayLikeObject} [out] - output array
* @param {Iterator} iterator - source iterator
* @param {Function} [mapFcn] - function to invoke for each iterated value
* @param {*} [thisArg] - execution context
* @throws {TypeError} iterator argument must be an iterator
* @throws {TypeError} callback argument must be a function
* @returns {ArrayLikeObject} output array
*
* @example
* var randu = require( '@stdlib/random/iterators/randu' );
*
* var iter = randu({
*     'iter': 10
* });
*
* var arr = iterator2array( iter );
* // returns <Array>
*/
function iterator2array() {
	var iterator;
	var thisArg;
	var fcn;
	var out;
	var len;
	var i;
	var v;
	if ( arguments.length === 1 ) {
		iterator = arguments[ 0 ];
	} else if ( arguments.length > 1 ) {
		if ( isArrayLikeObject( arguments[ 0 ] ) ) {
			out = arguments[ 0 ];
			iterator = arguments[ 1 ];
			if ( arguments.length > 2 ) {
				fcn = arguments[ 2 ];
				if ( !isFunction( fcn ) ) {
					throw new TypeError( 'invalid argument. Callback argument must be a function. Value: `' + fcn + '`.' );
				}
				thisArg = arguments[ 3 ];
			}
		} else {
			iterator = arguments[ 0 ];
			fcn = arguments[ 1 ];
			if ( !isFunction( fcn ) ) {
				throw new TypeError( 'invalid argument. Callback argument must be a function. Value: `' + fcn + '`.' );
			}
			thisArg = arguments[ 2 ];
		}
	}
	if ( iterator === null || typeof iterator !== 'object' || !isFunction( iterator.next ) ) {
		throw new TypeError( 'invalid argument. Iterator argument must be an iterator protocol-compliant object. Value: `' + iterator + '`.' );
	}
	i = -1;
	if ( out === void 0 ) {
		out = [];
		if ( fcn ) {
			while ( true ) {
				i += 1;
				v = iterator.next();
				if ( hasOwnProp( v, 'value' ) ) {
					out.push( fcn.call( thisArg, v.value, i ) );
				}
				if ( v.done ) {
					break;
				}
			}
			return out;
		}
		while ( true ) {
			v = iterator.next();
			if ( hasOwnProp( v, 'value' ) ) {
				out.push( v.value );
			}
			if ( v.done ) {
				break;
			}
		}
		return out;
	}
	len = out.length;
	if ( fcn ) {
		while ( i < len-1 ) {
			i += 1;
			v = iterator.next();
			if ( hasOwnProp( v, 'value' ) ) {
				out[ i ] = fcn.call( thisArg, v.value, i );
			}
			if ( v.done ) {
				break;
			}
		}
		return out;
	}
	while ( i < len-1 ) {
		i += 1;
		v = iterator.next();
		if ( hasOwnProp( v, 'value' ) ) {
			out[ i ] = v.value;
		}
		if ( v.done ) {
			break;
		}
	}
	return out;
}

// EXPORTS //

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

'use strict';

// MODULES //

var isFunction = require( '@stdlib/assert/is-function' );
var isArrayLikeObject = require( '@stdlib/assert/is-array-like-object' );
var isIteratorLike = require( '@stdlib/assert/is-iterator-like' );
var hasOwnProp = require( '@stdlib/assert/has-own-property' );

// MAIN //

/**
* Creates (or fills) an array from an iterator.
*
* @param {ArrayLikeObject} [out] - output array
* @param {Iterator} iterator - source iterator
* @param {Function} [mapFcn] - function to invoke for each iterated value
* @param {*} [thisArg] - execution context
* @throws {TypeError} iterator argument must be an iterator
* @throws {TypeError} callback argument must be a function
* @returns {ArrayLikeObject} output array
*
* @example
* var randu = require( '@stdlib/random/iterators/randu' );
*
* var iter = randu({
*     'iter': 10
* });
*
* var arr = iterator2array( iter );
* // returns <Array>
*/
function iterator2array() {
	var iterator;
	var thisArg;
	var fcn;
	var out;
	var len;
	var i;
	var v;
	if ( arguments.length === 1 ) {
		iterator = arguments[ 0 ];
	} else if ( arguments.length > 1 ) {
		if ( isArrayLikeObject( arguments[ 0 ] ) ) {
			out = arguments[ 0 ];
			iterator = arguments[ 1 ];
			if ( arguments.length > 2 ) {
				fcn = arguments[ 2 ];
				if ( !isFunction( fcn ) ) {
					throw new TypeError( 'invalid argument. Callback argument must be a function. Value: `' + fcn + '`.' );
				}
				thisArg = arguments[ 3 ];
			}
		} else {
			iterator = arguments[ 0 ];
			fcn = arguments[ 1 ];
			if ( !isFunction( fcn ) ) {
				throw new TypeError( 'invalid argument. Callback argument must be a function. Value: `' + fcn + '`.' );
			}
			thisArg = arguments[ 2 ];
		}
	}
	if ( !isIteratorLike( iterator ) ) {
		throw new TypeError( 'invalid argument. Iterator argument must be an iterator protocol-compliant object. Value: `' + iterator + '`.' );
	}
	i = -1;
	if ( out === void 0 ) {
		out = [];
		if ( fcn ) {
			while ( true ) {
				i += 1;
				v = iterator.next();
				if ( hasOwnProp( v, 'value' ) ) {
					out.push( fcn.call( thisArg, v.value, i ) );
				}
				if ( v.done ) {
					break;
				}
			}
			return out;
		}
		while ( true ) {
			v = iterator.next();
			if ( hasOwnProp( v, 'value' ) ) {
				out.push( v.value );
			}
			if ( v.done ) {
				break;
			}
		}
		return out;
	}
	len = out.length;
	if ( fcn ) {
		while ( i < len-1 ) {
			i += 1;
			v = iterator.next();
			if ( hasOwnProp( v, 'value' ) ) {
				out[ i ] = fcn.call( thisArg, v.value, i );
			}
			if ( v.done ) {
				break;
			}
		}
		return out;
	}
	while ( i < len-1 ) {
		i += 1;
		v = iterator.next();
		if ( hasOwnProp( v, 'value' ) ) {
			out[ i ] = v.value;
		}
		if ( v.done ) {
			break;
		}
	}
	return out;
}

// EXPORTS //

module.exports = iterator2array;
<|endoftext|>


<commit_before>'use strict';

/**
 * input controller
 *
 * @class
 * @version 0.1.0
 * @author Tomoyuki Kashiro <kashiro@github>
 * @license MIT
 */

angular.module('socialCounterApp')
  .controller('InputCtrl', ['$scope','$location', function ($scope, $location) {

    var targetUrl = '';

    $scope.onSubmit = function(url) {
      var ssid, path;
      targetUrl = url.trim();

      if(url === ''){
        return;
      }

      if(isGss(url)){
        path = url.split('?')[1];
        ssid = queryToObj(path).key;
        $location.path(ssid);
      }else{
        $location.path(encodeURIComponent(targetUrl));
      }
    };

    function isGss(url){
      return url.indexOf('https://docs.google.com/spreadsheet/ccc?key=') !== -1;
    }

    function queryToObj(query){
      var params, i = 0,
          q,
          kv,
          length,
          result = {};

      if(query === ''){
        return result;
      }

      query = query.replace(/^\?/, '');
      params = query.split('&');
      length = params.length;

      for (; i < length; i++) {
        q = params[i];
        kv = q.split('=');
        result[kv[0]] = decodeURIComponent(kv[1]);
      }
      return result;
    }

  }]);
<commit_msg>modify gss judge<commit_after>'use strict';

/**
 * input controller
 *
 * @class
 * @version 0.1.0
 * @author Tomoyuki Kashiro <kashiro@github>
 * @license MIT
 */

angular.module('socialCounterApp')
  .controller('InputCtrl', ['$scope','$location', function ($scope, $location) {

    var targetUrl = '';

    $scope.onSubmit = function(url) {
      var ssid, path;
      targetUrl = url.trim();

      if(url === ''){
        return;
      }

      if(isGss(url)){
        path = url.split('?')[1];
        ssid = queryToObj(path).key;
        $location.path(ssid);
      }else{
        $location.path(encodeURIComponent(targetUrl));
      }
    };

    function isGss(url){
      return url.indexOf('https://docs.google.com') !== -1;
    }

    function queryToObj(query){
      var params, i = 0,
          q,
          kv,
          length,
          result = {};

      if(query === ''){
        return result;
      }

      query = query.replace(/^\?/, '');
      params = query.split('&');
      length = params.length;

      for (; i < length; i++) {
        q = params[i];
        kv = q.split('=');
        result[kv[0]] = decodeURIComponent(kv[1]);
      }
      return result;
    }

  }]);
<|endoftext|>


<commit_before>elation.require([
  "physics.cyclone",
  "physics.forces",
  "physics.constraints",
  "physics.collisions",
  "physics.processors"
]);

elation.extend("engine.systems.physics", function(args) {
  elation.implement(this, elation.engine.systems.system);

  this.system_attach = function(ev) {
    console.log('INIT: physics');
  }
  this.engine_start = function(ev) {
    //console.log("PHYSICS: starting");
    elation.physics.system.start();
  }
  this.engine_frame = function(ev) {
    //console.log("FRAME: physics");
    elation.physics.system.step(ev.data.delta);
  }
  this.engine_stop = function(ev) {
    console.log('SHUTDOWN: physics');
  }
});

<commit_msg>Added physics timescale factor and force visualizers<commit_after>elation.require(["physics.cyclone"]);

elation.extend("engine.systems.physics", function(args) {
  elation.implement(this, elation.engine.systems.system);
  this.timescale = 1;
  this.debugwindows = {};
  this.debugvis = {};
  this.debugthings = {};

  this.system_attach = function(ev) {
    console.log('INIT: physics');
    this.initstats();
  }
  this.engine_start = function(ev) {
    //console.log("PHYSICS: starting");
    elation.physics.system.start();
    this.lasttime = new Date().getTime();
    if (this.interval) {
      clearInterval(this.interval);
    }
/*
    this.interval = setInterval(elation.bind(this, function() {
      var now = new Date().getTime();
        elation.physics.system.step(this.timescale * (now - this.lasttime) / 1000);
        if (this.stats) this.stats.update();
      this.lasttime = now;
    }), 1000/40);
*/
  }
  this.engine_frame = function(ev) {
    //console.log("FRAME: physics");
    this.step(ev.data.delta);
  }
  this.engine_stop = function(ev) {
    console.log('SHUTDOWN: physics');
    if (this.interval) {
      clearInterval(this.interval);
      this.interval = false;
    }
  }
  this.initstats = function() {
    this.stats = new Stats();
    this.stats.domElement.style.position = 'absolute';
    this.stats.domElement.style.top = '0px';
    this.stats.domElement.style.zIndex = 100;
    document.body.appendChild(this.stats.domElement);
    this.stats.domElement.style.left = this.stats.domElement.offsetWidth + 'px';
    this.stats.domElement.childNodes[0].childNodes[0].style.color = '#900';
    this.stats.domElement.childNodes[0].childNodes[1].style.backgroundColor = '#900';
  }
  this.add = function(obj) {
    elation.physics.system.add(obj);
  }
  this.remove = function(obj) {
    elation.physics.system.remove(obj);
  }
  this.step = function(delta) {
    elation.physics.system.step(this.timescale * delta);
    if (this.stats) this.stats.update();
    if (this.debugthing) {
      this.debugupdate(this.debugthing);
    }
  }
  this.debug = function(thing) {
    if (!this.debugwindows[thing.name]) {
      this.debugwindows[thing.name] = elation.ui.window(null, elation.html.create({tag: 'div', append: document.body}), {title: "Physics Debug - " + thing.name, center: true, right: 10});
      this.debugwindows[thing.name].setcontent(elation.html.create('ul'));
      elation.events.add(this.debugwindows[thing.name], 'ui_window_close', elation.bind(this, function(ev) {
        console.log('REMOVE IT', thing.name);
        this.debugvis[thing.name].die();
        this.debugvis[thing.name] = false;
        if (thing == this.debugthing) this.debugthing = false;
        this.debugwindows[thing.name] = false;
        delete this.debugthings[thing.name];
      }));

    }
    if (!this.debugvis[thing.name]) {
      this.debugvis[thing.name]= thing.spawn('physics_vis', thing.name + '_physvis', {target: thing, pickable: false, persist: false, physical: false});
    }
    if (!this.debugthings[thing.name]) {
      this.debugthings[thing.name] = thing;
    }
/*
    if (!this.debugvis[thing.name].parent || this.debugvis[thing.name].parent != thing || this.debugvis[thing.name].objects['3d'].parent != thing.objects['3d']) {
      this.debugvis[thing.name].reparent(thing);
    }
*/
    this.debugwindows[thing.name].focus();
    this.debugthing = thing;
    this.debugupdate(thing);
  }
  this.debugupdate = function(thing) {
    for (var name in this.debugthings) {
      var thing = this.debugthings[name];
      var win = this.debugwindows[name];
      var ul = win.content;
      ul.innerHTML = '';
      var values = ['state', 'mass', 'position', 'velocity', 'acceleration', 'angular', 'angularaccel', 'force_accumulator', 'damping'];
      if (thing.objects.dynamics) {
        for (var i = 0; i < values.length; i++) {
          var li = elation.html.create('li');
          var content = "<strong>" + values[i] + ":</strong> ";
          var value = thing.objects.dynamics[values[i]];
          if (value instanceof THREE.Vector3) {
            content += "[ " + value.x.toFixed(4) + ", " + value.y.toFixed(4) + ", " + value.z.toFixed(4) + " ]";
          } else if (values[i] == 'state') {
            for (var k in value) {
              var tag = (value[k] ? "add" : "del");
              content += "<" + tag + ">" + k + "</" + tag + "> ";
            }
          } else if (values[i] == 'damping') {
            content += "[" + thing.objects.dynamics.linearDamping + ', ' + thing.objects.dynamics.angularDamping + "]";
          } else {
            content += value;
          }
          li.innerHTML = content;
          ul.appendChild(li);
        }
      } else {
        this.debugwindows[thing.name].close();
      }
    }
  }
});
elation.component.add("engine.things.physics_vis", function(args) {
  this.postinit = function() {
    this.defineProperties({
      target: { type: 'thing' },
      forcescale: { type: 'float', default: .1 }
    });
  }
  this.createObject3D = function() {
    //this.objects['3d'] = new THREE.Object3D();
    this.objects['3d'] = new THREE.Object3D();

    var obj = this.properties.target;
    if (obj.objects['3d'] && obj.objects['3d'].geometry) {
      if (!obj.objects['3d'].geometry.boundingBox) {
        obj.objects['3d'].geometry.computeBoundingBox();
      }
      var bbox = obj.objects['3d'].geometry.boundingBox;
      this.spawn('physics_collider', this.name + '_collider', {body: obj.objects['dynamics'], pickable: false, mouseevents: false, persist: false, physical: false});

      if (obj.objects['dynamics']) {
        var forceargs = {
          body: obj.objects['dynamics'],
          boundingbox: bbox,
          forcescale: this.properties.forcescale,
          pickable: false,
          mouseevents: false,
          persist: false,
          physical: false
        };
        for (var k in obj.objects['dynamics'].forces) {
          forceargs.force = obj.objects['dynamics'].forces[k];
          var type = false;
          for (var f in elation.physics.forces) {
            if (forceargs.force instanceof elation.physics.forces[f]) {
              this.spawn('physics_forces_' + f, obj.name + '_force_' + f + '_' + k, forceargs);
            }
          }
        }
      }

    }
    return this.objects['3d'];
  }

}, elation.engine.things.generic);
elation.component.add("engine.things.physics_collider", function(args) {
  this.postinit = function() {
    this.defineProperties({
      body:        {type: 'object'},
      boundingbox: { type: 'object' },
      forcescale: { type: 'float', default: .1 }
    });
    elation.events.add(this.properties.body, 'physics_collide', this);
    this.collisioncount = 0;
  }
  this.createObject3D = function() {
    if (this.objects['3d']) return this.objects['3d'];
    var collider = this.properties.body.collider;
    var obj = false;
    switch (collider.type) {
      case 'sphere':
        obj = this.createBoundingSphere(collider);
        break;
      case 'plane':
        obj = this.createBoundingPlane(collider);
        break;
      case 'box':
      default:
        obj = this.createBoundingBox(collider);
        break;
    }
    if (this.properties.body.mass > 0) {
      var cg = this.createCG();
      obj.add(cg);
    }
    return obj;
  }
  this.createBoundingBox = function(collider) {
    var bbox = collider;

    var corners = [
      [bbox.min.x, bbox.max.y, bbox.min.z],
      [bbox.max.x, bbox.max.y, bbox.min.z],
      [bbox.max.x, bbox.max.y, bbox.max.z],
      [bbox.min.x, bbox.max.y, bbox.max.z],
      [bbox.min.x, bbox.min.y, bbox.min.z],
      [bbox.max.x, bbox.min.y, bbox.min.z],
      [bbox.max.x, bbox.min.y, bbox.max.z],
      [bbox.min.x, bbox.min.y, bbox.max.z],
    ];
    var edges = [
      // top
      [corners[0], corners[1]],
      [corners[1], corners[2]],
      [corners[2], corners[3]],
      [corners[3], corners[0]],
      // bottom
      [corners[4], corners[5]],
      [corners[5], corners[6]],
      [corners[6], corners[7]],
      [corners[7], corners[4]],
      // sides
      [corners[0], corners[4]],
      [corners[1], corners[5]],
      [corners[2], corners[6]],
      [corners[3], corners[7]]
    ]
    var linegeo = new THREE.Geometry();
    for (var i = 0; i < edges.length; i++) {
      var edge = edges[i];
      linegeo.vertices.push(new THREE.Vector3(edge[0][0], edge[0][1], edge[0][2]));
      linegeo.vertices.push(new THREE.Vector3(edge[1][0], edge[1][1], edge[1][2]));
    }
    //var boxgeo = new THREE.CubeGeometry(bbox.max.x - bbox.min.x, bbox.max.y - bbox.min.y, bbox.max.z - bbox.min.z);
    var boxmat = new THREE.LineBasicMaterial({color: 0x00ffff, transparent: true, depthWrite: false, depthTest: false, opacity: .5, blending: THREE.AdditiveBlending});
    var outline = new THREE.Line(linegeo, boxmat, THREE.LinePieces);

    var volume = new THREE.Mesh(new THREE.CubeGeometry(bbox.max.x - bbox.min.x, bbox.max.y - bbox.min.y, bbox.max.z - bbox.min.z, 10, 10, 10), new THREE.MeshPhongMaterial({color: 0xaaaaaa, emissive: 0x666666, depthTest: true, depthWrite: true, opacity: .1, transparent: true}));
    volume.position.addVectors(bbox.max, bbox.min).multiplyScalar(.5);
console.log(this.properties.body);
    outline.add(volume);
    //outline.add(new THREE.AxisHelper(.5));

    // temporary helpers for debugging coordinate space transforms
/*
    var forward = new THREE.Vector3(0,0,-1);
    this.arrows = {
      forward: new THREE.ArrowHelper(forward, new THREE.Vector3(0,0,0), 2, 0x00ffff),
      forward_world: new THREE.ArrowHelper(this.properties.body.getWorldDirection(forward.clone()), new THREE.Vector3(0,0,0), 2, 0x00ff66),
      forward_local: new THREE.ArrowHelper(this.properties.body.getLocalDirection(forward.clone()), new THREE.Vector3(0,0,0), 2, 0x0066ff)
    };
    outline.add(this.arrows.forward);
    outline.add(this.arrows.forward_world);
    outline.add(this.arrows.forward_local);
    elation.events.add(this.properties.body.object.engine, 'engine_frame', this);
*/
    return outline;
  }
  this.createBoundingSphere = function(collider) {
    //var spheregeo = new THREE.SphereGeometry(collider.radius, 18, 9);
    var spheregeo = new THREE.IcosahedronGeometry(collider.radius, 2);
    var spheremat = new THREE.MeshBasicMaterial({color: 0x00ffff, transparent: true, opacity: .2, depthWrite: false, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: 1, wireframe: false, blending: THREE.AdditiveBlending});
    var spherewiremat = new THREE.MeshBasicMaterial({color: 0xff0000, transparent: true, opacity: .1, depthWrite: false, depthTest: false, wireframe: true, blending: THREE.AdditiveBlending});
    var outline = new THREE.Mesh(spheregeo, spherewiremat);
    //outline.add(new THREE.Mesh(spheregeo, spheremat));
    return outline;
  }
  this.createBoundingPlane = function(collider) {
    var plane = new THREE.PlaneGeometry(1000, 1000);
    var planemat = new THREE.MeshBasicMaterial({color: 0x00ffff, transparent: true, opacity: .04, depthWrite: false, polygonOffset: true, polygonOffsetFactor: -1, polygonOffsetUnits: 1, wireframe: false, blending: THREE.AdditiveBlending });
// FIXME - this only really works for horizontal planes
var mat = new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0), -Math.PI/2));
plane.applyMatrix(mat);
console.log(mat.toArray());
    var mesh = new THREE.Mesh(plane, planemat);
    return mesh;
  }
  this.createCG = function() {
    // Create yellow checkerboard texture
    var cgmatcanvas = elation.html.create('canvas');
    var cw = 128, ch = 64;
    cgmatcanvas.width = cw;
    cgmatcanvas.height = ch;
    var ctx = cgmatcanvas.getContext('2d');
    ctx.fillStyle = 'yellow';
    ctx.fillRect(0, 0, cw, ch);
    ctx.fillStyle = 'black';
    ctx.fillRect(0, 0, cw/2, ch/2);
    ctx.fillRect(cw/2, ch/2, cw, ch);
    var tex = new THREE.Texture(cgmatcanvas);
    tex.minFilter = tex.maxFilter = THREE.LinearFilter;
    tex.needsUpdate = true;

    var cg = new THREE.Mesh(new THREE.SphereGeometry(.05), new THREE.MeshPhongMaterial({emissive: 0x666600, map: tex, transparent: true, depthWrite: false, depthTest: false, opacity: 1}));
    return cg;
  }
  this.engine_frame = function() {
    var forward = new THREE.Vector3(0,0,-1);
    this.arrows.forward.setDirection(forward);
    this.arrows.forward_world.setDirection(this.properties.body.getWorldDirection(forward.clone()));
    this.arrows.forward_local.setDirection(this.properties.body.getLocalDirection(forward.clone()));
  }
  this.physics_collide = function(ev) {
    var collision = ev.data;
    // FIXME - this is inefficient as all hell.  We should use a particle system, or at LEAST re-use and limit the max collisions visualized at once
    this.spawn('physics_collision', this.name + '_collision_' + ev.timeStamp, {
      collision: collision,
      position: collision.point,
      pickable: false,
      mouseevents: false,
      persist: false,
      physical: false
    }, true);
  }
}, elation.engine.things.generic);

elation.component.add("engine.things.physics_collision", function(args) {
  this.postinit = function() {
    this.defineProperties({
      collision:  {type: 'object'},
      forcescale: { type: 'float', default: .1 },
      fadetime: { type: 'float', default: 1.0 }
    });
    this.spawntime = new Date().getTime();
    this.elapsed = 0;
    elation.events.add(this.engine, 'engine_frame', this);
  }
  this.createObject3D = function() {
    this.materials = [];
    var collision = this.properties.collision;
    var planegeo = new THREE.PlaneGeometry(1, 1);
    var planemat = new THREE.MeshBasicMaterial({
      map: this.generateGrid(0xff0000),
      wireframe: false,
      transparent: true,
      depthWrite: false,
      polygonOffset: true,
      polygonOffsetUnits: 1,
      polygonOffsetFactor: -1,
      side: THREE.DoubleSide,
    });
    var plane = new THREE.Mesh(planegeo, planemat);
    var obj = new THREE.Object3D();
    obj.add(plane);
    plane.lookAt(collision.normal);
    this.materials.push(planemat);
    this.objects['3d'] = obj;

console.log('IMPULSES', collision, collision.impulses);
    var origin = new THREE.Vector3(0,0,0);
    for (var i = 0; i < collision.impulses.length; i++) {
      if (collision.impulses[i]) {
        var len = collision.impulses[i].length();
        if (len > 0) {
          var dir = collision.impulses[i].clone().divideScalar(len);
          var impulsearrow = this.generateArrow(dir, origin, len * this.properties.forcescale, 0x990099);
          //obj.add(impulsearrow);
          // FIXME - need to remove object from proper parent when done fading
          collision.bodies[i].object.objects['3d'].add(impulsearrow);
        }
      }
    }

    var m = collision.contactToWorld.elements;
    var arrowaxisx = this.generateArrow(new THREE.Vector3(m[0], m[1], m[2]), origin, 1, 0xff0000);
    obj.add(arrowaxisx);
    var arrowaxisy = this.generateArrow(new THREE.Vector3(m[4], m[5], m[6]), origin, 1, 0x00ff00);
    obj.add(arrowaxisy);
    var arrowaxisz = this.generateArrow(new THREE.Vector3(m[8], m[9], m[10]), origin, 1, 0x0000ff);
    obj.add(arrowaxisz);

    return obj;
  }
  this.generateArrow = function(dir, origin, len, color) {
    var arrow = new THREE.ArrowHelper(dir, origin, len, color);
    for (var j = 0; j < arrow.children.length; j++) {
      var mat = arrow.children[j].material;
      mat.transparent = true;
      mat.depthWrite = mat.depthTest = false;
      this.materials.push(mat);
    }
    return arrow;
  }
  this.generateGrid = function(color, lines) {
    if (!color) color = 0xff0000;
    if (!lines) lines = 10;

    var canvas = elation.html.create('canvas');
    var cw = 512, ch = 512;
    var gridsize = cw / lines;

    canvas.width = cw;
    canvas.height = ch;
    var ctx = canvas.getContext('2d');

    ctx.fillStyle = 'rgba(255,0,0,.25)';
    ctx.fillRect(0, 0, cw, ch);
    ctx.strokeStyle = 'rgba(255,0,0,.5)';

    for (var y = 0; y <= lines; y++) {
      for (var x = 0; x <= lines; x++) {
        ctx.beginPath();
        ctx.moveTo(0, y * gridsize);
        ctx.lineTo(cw, y * gridsize);
        ctx.stroke();

        ctx.beginPath();
        ctx.moveTo(x * gridsize, 0);
        ctx.lineTo(x * gridsize, ch);
        ctx.stroke();
      }
    }
    ctx.globalCompositeOperation = 'destination-out';
    var grd = ctx.createRadialGradient(cw/2,ch/2,0,cw/2,ch/2,cw/2);
    grd.addColorStop(0, 'rgba(0,0,0,.5)');
    grd.addColorStop(.5, 'rgba(0,0,0,.5)');
    grd.addColorStop(1, 'rgba(0,0,0,1)');
    ctx.fillStyle = grd;
    ctx.fillRect(0,0,cw,ch);

    ctx.globalCompositeOperation = 'source-over';
    ctx.fillStyle = '#ff0000';
    ctx.strokeStyle = '#990000';
    ctx.lineWidth = 3;
    ctx.beginPath();
    ctx.arc(cw/2, ch/2, 8, 0, 2 * Math.PI, false);
    ctx.fill();
    ctx.stroke();

    var tex = new THREE.Texture(canvas);
    tex.minFilter = tex.maxFilter = THREE.LinearFilter;
    tex.needsUpdate = true;
    return tex;
  }
  this.engine_frame = function(ev) {
    var fadetime = this.properties.fadetime;
    this.elapsed += ev.data.delta * this.engine.systems.physics.timescale;
    var opacity = (fadetime - this.elapsed) / fadetime;
    if (opacity > 0) {
      for (var i = 0; i < this.materials.length; i++) {
        this.materials[i].opacity = opacity;
      }
    } else {
      elation.events.remove(this.engine, 'engine_frame', this);
      this.die();
    }
  }
}, elation.engine.things.generic);

elation.component.add("engine.things.physics_forces_gravity", function(args) {
  this.postinit = function() {
    this.defineProperties({
      body:        {type: 'object'},
      force:       {type: 'object'},
      boundingbox: {type: 'object'},
      forcescale:  {type: 'float'}
    });
    elation.events.add(this.properties.force, 'physics_force_apply', this);
  }
  this.createObject3D = function() {
    var grav = this.properties.body.getLocalDirection(this.properties.force.gravsum.clone());
    var len = grav.length();
    grav.divideScalar(len);
    this.arrow = new THREE.ArrowHelper(grav, new THREE.Vector3(0,0,0), len, 0xff00ff);
    this.arrow.children[0].material.transparent = true;
    this.arrow.children[0].material.opacity = 0.5;
    this.arrow.children[0].material.depthWrite = this.arrow.children[0].material.depthTest = false;
    this.arrow.children[1].material.depthWrite = this.arrow.children[0].material.depthTest = false;
    var obj = new THREE.Object3D();
    obj.add(this.arrow);

    var labeltext = elation.engine.utils.materials.getTextureLabel('Hello cool');
    //var labelgeo = new THREE.PlaneGeometry(labeltext.image.width / 100, labeltext.image.height / 100);
    //var label = new THREE.Mesh(labelgeo, new THREE.MeshBasicMaterial({map: labeltext, side: THREE.DoubleSide, transparent: true, depthWrite: false, depthTest: false}));
var mapB = THREE.ImageUtils.loadTexture( "/media/space/textures/sprite1.png" );
    var label = new THREE.Sprite(new THREE.SpriteMaterial({map: labeltext, useScreenCoordinates: false, sizeAttenuation: false, color: 0xffffff }));
    label.position.set(1.5, 1.5, 0)
    //label.scale.set(labeltext.image.width/100,labeltext.image.height/100,1);
    obj.add(label);

    return obj;
  }
  this.physics_force_apply = function() {
    var grav = this.properties.body.getLocalDirection(this.properties.force.gravsum.clone());
    var len = grav.length();
    grav.divideScalar(len);
    this.arrow.setDirection(grav);
    this.arrow.setLength(len / this.properties.body.mass * this.properties.forcescale);
  }
}, elation.engine.things.generic);

elation.component.add("engine.things.physics_forces_buoyancy", function(args) {
  this.postinit = function() {
    this.defineProperties({
      body:        {type: 'object'},
      force:       {type: 'object'},
      boundingbox: {type: 'object'},
      forcescale:  {type: 'float'}
    });
    elation.events.add(this.properties.force, 'physics_force_apply', this);
  }
  this.createObject3D = function() {
    var obj = new THREE.Object3D();
    var bbox = this.properties.boundingbox;
    var size = [bbox.max.x - bbox.min.x, bbox.max.y - bbox.min.y, bbox.max.z - bbox.min.z];
    var insidegeo = new THREE.CubeGeometry(size[0], size[1], size[2]);
    insidegeo.applyMatrix(new THREE.Matrix4().makeTranslation(0, size[1]/2, 0));
    var insidemat_side = new THREE.MeshPhongMaterial({emissive: 0x006666, color: 0x00ffff, opacity: 0.2, transparent: true, depthWrite: false, depthTest: false});
    var insidemat_top = new THREE.MeshPhongMaterial({emissive: 0x006666, color: 0x00ffff, opacity: 0.5, transparent: true, depthWrite: false, depthTest: false});

    this.inside = new THREE.Mesh(insidegeo, new THREE.MeshFaceMaterial([insidemat_side, insidemat_side, insidemat_side, insidemat_top, insidemat_side, insidemat_side]));
    this.inside.scale.y = this.properties.force.submerged;
    this.inside.position.y = -size[1] / 2;
    obj.add(this.inside);

    this.arrow = new THREE.ArrowHelper(new THREE.Vector3(0,1,0), this.properties.force.position, 1, 0xff00ff);
    this.arrow.children[0].material.transparent = true;
    this.arrow.children[0].material.opacity = 0.5;
    this.arrow.children[0].material.depthWrite = this.arrow.children[0].material.depthTest = false;
    this.arrow.children[1].material.depthWrite = this.arrow.children[0].material.depthTest = false;
    obj.add(this.arrow);

    return obj;
  }
  this.physics_force_apply = function(ev) {
    this.inside.scale.y = Math.max(0.01, this.properties.force.submerged);
    var len = this.properties.force.force.length();
    var grav = this.properties.body.getLocalDirection(new THREE.Vector3(0,1,0));
    if (len > .1) {
      if (!this.arrow.parent) {
        this.objects['3d'].add(this.arrow);
      }
//console.log('length is', len, this.properties.force.force.toArray());
      this.arrow.setLength(len / this.properties.body.mass * this.properties.forcescale);
      this.arrow.setDirection(grav);
    } else {
        this.objects['3d'].remove(this.arrow);
//console.log('HIDEY length is', len, this.properties.force.force.toArray());
    }
//console.log('ARROW', this.arrow);
  }
}, elation.engine.things.generic);

elation.component.add("engine.things.physics_forces_spring", function(args) {
  this.postinit = function() {
    this.defineProperties({
      body:        {type: 'object'},
      force:       {type: 'object'},
      boundingbox: {type: 'object'},
      forcescale:  {type: 'float'}
    });
    elation.events.add(this.properties.force, 'physics_force_apply', this);
  }
  this.createObject3D = function() {
    var obj = new THREE.Object3D();

    this.arrow = new THREE.ArrowHelper(new THREE.Vector3(0,1,0), this.properties.force.connectionpoint, 1, 0xff00ff);
    this.arrow.children[0].material.transparent = true;
    this.arrow.children[0].material.opacity = 0.5;
    this.arrow.children[0].material.depthWrite = this.arrow.children[0].material.depthTest = false;
    this.arrow.children[1].material.depthWrite = this.arrow.children[0].material.depthTest = false;
    obj.add(this.arrow);

    return obj;
  }
  this.physics_force_apply = function(ev) {
    var force = this.properties.force.force.clone();
    var length = force.length();
    if (length > 0) {
      if (this.arrow.parent != this.objects['3d']) {
        this.objects['3d'].add(this.arrow);
      }
      force.divideScalar(length);
      this.arrow.setLength(length * this.properties.forcescale);
      this.arrow.setDirection(force);
    } else if (this.arrow.parent == this.objects['3d']) {
      this.objects['3d'].remove(this.arrow);
    }
  }
}, elation.engine.things.generic);
<|endoftext|>