<commit_before>/*
 * Spreed Speak Freely.
 * Copyright (C) 2013-2014 struktur AG
 *
 * This file is part of Spreed Speak Freely.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'], function(_, templateChat, templateChatroom) {

    return ["$compile", "safeDisplayName", "mediaStream", "safeApply", "desktopNotify", "translation", "playSound", "fileUpload", "randomGen", "buddyData", "$timeout", function($compile, safeDisplayName, mediaStream, safeApply, desktopNotify, translation, playSound, fileUpload, randomGen, buddyData, $timeout) {

        var displayName = safeDisplayName;
        var group_chat_id = "";

        var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {

            $scope.layout.chat = false;
            $scope.layout.chatMaximized = false;

            var ctrl = this;
            var rooms = ctrl.rooms = {};
            ctrl.visibleRooms = [];
            ctrl.group = group_chat_id;
            ctrl.get = function(id) {
                return ctrl.rooms[id];
            }

            $scope.currentRoom = null;
            $scope.currentRoomActive = false;
            $scope.getVisibleRooms = function() {
                var res = [];
                for (var i=0; i<ctrl.visibleRooms.length; i++) {
                    var r = rooms[ctrl.visibleRooms[i]];
                    if (!r || r.id === ctrl.group) {
                        continue;
                    }
                    res.push(r);
                }
                return res;
            };
            $scope.getGroupRoom = function() {
                return rooms[ctrl.group];
            };

            mediaStream.api.e.on("received.chat", function(event, id, from, data, p2p) {

                //console.log("received", data, id, from);

                var roomid = id;
                if (roomid === mediaStream.api.id) {
                    roomid = from;
                } else {
                    if (roomid !== ctrl.group && from !== mediaStream.api.id) {
                        console.log("Received chat message for invalid room", roomid, id, from);
                        return;
                    }
                }

                var with_message = !!data.Message;
                var room = rooms[roomid];
                if (!room) {
                    if (!with_message) {
                        return;
                    }
                    // No room with this id, get one with the from id
                    $scope.$emit("startchat", from, {restore: with_message});
                    room = rooms[from];
                }

                if (with_message && from !== mediaStream.api.id) {
                    room.newmessage = true;
                    room.peerIsTyping = "no";
                    room.p2p(!!p2p);
                }

                room.$broadcast("received", from, data);
                safeApply(room);

            });

            mediaStream.api.e.on("received.userleftorjoined", function(event, dataType, data) {
                var room = rooms[data.Id];
                if (room) {
                    switch (dataType) {
                    case "Left":
                        if (data.Status !== "soft") {
                            room.enabled = false;
                            room.$broadcast("received", data.Id, {Type: "LeftOrJoined", "LeftOrJoined": "left"});
                            safeApply(room);
                        }
                        break;
                    case "Joined":
                        if (!room.enabled) {
                            room.enabled = true;
                            _.delay(function() {
                                room.$broadcast("received", data.Id, {Type: "LeftOrJoined", "LeftOrJoined": "joined"});
                                safeApply(room);
                            }, 1000);
                        }
                        break;
                    default:
                        break;
                    }
                }
            });

            $scope.$parent.$on("startchat", function(event, id, options) {

                //console.log("startchat requested", event, id);
                if (id === group_chat_id) {
                    $scope.showGroupRoom(null, options);
                } else {
                    $scope.showRoom(id, {title: translation._("Chat with")}, options);
                }

            });

        }];

        var compile = function(tElement, tAttrs) {

            var chat = $compile(templateChatroom);
            return function(scope, iElement, iAttrs, controller) {

                var pane = iElement.find(".chatpane");

                scope.showGroupRoom = function(settings, options) {
                    var stngs = $.extend({title: translation._("Room chat")}, settings);
                    return scope.showRoom(controller.group, stngs, options);
                };

                scope.showRoom = function(id, settings, options) {
                    var options = $.extend({}, options);
                    var subscope = controller.rooms[id];
                    var index = controller.visibleRooms.length;
                    if (!subscope) {
                        console.log("Create new chatroom", [id]);
                        controller.visibleRooms.push(id);
                        subscope = controller.rooms[id] = scope.$new();
                        translation.inject(subscope);
                        subscope.id = id;
                        subscope.isgroupchat = id === controller.group ? true : false;
                        subscope.index = index;
                        subscope.settings = settings;
                        subscope.visible = false;
                        subscope.newmessage = false;
                        subscope.enabled = true;
                        subscope.peerIsTyping = "no";
                        subscope.firstmessage = true;
                        subscope.p2pstate = false;
                        subscope.active = false;
                        subscope.pending = 0;
                        if (!subscope.isgroupchat) {
                            buddyData.push(id);
                        }
                        subscope.hide = function() {
                            scope.hideRoom(id);
                        };
                        //TODO(longsleep): This is currently never called. Find a suitable way to clean up old chats.
                        subscope.kill = function() {
                            if (!subscope.isgroupchat) {
                                buddyData.pop(id);
                            }
                            scope.killRoom(id);
                        };
                        subscope.seen = function() {
                            subscope.pending = 0;
                            scope.$emit("chatseen", subscope.id);
                            if (subscope.newmessage) {
                                subscope.newmessage = false;
                                subscope.$broadcast("seen");
                            }
                        };
                        subscope.deactivate =function() {
                            scope.deactivateRoom();
                        };
                        subscope.toggleMax = function() {
                            scope.toggleMax();
                        };
                        subscope.sendChat = function(to, message, status, mid, noloop) {
                            //console.log("send chat", to, scope.peer);
                            var peercall = mediaStream.webrtc.findTargetCall(to);
                            if (message && !mid) {
                                mid = randomGen.random({hex: true});
                            };
                            if (peercall && peercall.peerconnection.datachannelReady) {
                                subscope.p2p(true);
                                // Send out stuff through data channel.
                                _.delay(function() {
                                    mediaStream.api.apply("sendChat", {
                                        send: function(type, data) {
                                            // We also send to self, to display our own stuff.
                                            if (!noloop) {
                                                mediaStream.api.received({Type: data.Type, Data: data, From: mediaStream.api.id, To: peercall.id});
                                            }
                                            return peercall.peerconnection.send(data);
                                        }
                                    })(to, message, status, mid);
                                }, 100);

                            } else {
                                subscope.p2p(false);
                                _.delay(function() {
                                    mediaStream.api.send2("sendChat", function(type, data) {
                                        if (!noloop) {
                                            //console.log("looped to self", type, data);
                                            mediaStream.api.received({Type: data.Type, Data: data, From: mediaStream.api.id, To: to});
                                        }
                                    })(to, message, status, mid);
                                }, 100);
                            }
                            return mid;
                        };
                        subscope.p2p = function(state) {
                            if (state !== subscope.p2pstate) {
                                subscope.p2pstate = state;
                                subscope.$broadcast("p2p", state);
                            }
                        };
                        //console.log("Creating new chat room", controller, subscope, index);
                        subscope.$on("submit", function(event, input) {
                            subscope.seen();
                            var mid = subscope.sendChat(event.targetScope.id, input);
                            event.targetScope.$broadcast("received", null, {Type: "Message", Status: {State: "sent", "Mid": mid}});
                        });
                        subscope.$on("submitseen", function(event, pending) {
                            //console.log("submitseen", pending);
                            subscope.sendChat(event.targetScope.id, null, {SeenMids: pending}, null, true);
                        });
                        subscope.$on("submitreceived", function(event, mid) {
                            subscope.sendChat(event.targetScope.id, null, {State: "delivered", Mid: mid}, null, true);
                        });
                        subscope.$on("typing", function(event, params) {
                            if (params.who === "local") {
                                var room = event.targetScope.id;
                                subscope.seen();
                                //console.log("typing event", params.status);
                                if (!subscope.isgroupchat) {
                                    // Transmit typing events to private chats.
                                    subscope.sendChat(event.targetScope.id, null, {Typing: params.status});
                                }
                            } else {
                                subscope.peerIsTyping = params.status;
                                //console.log("peer typing event", params.status, subscope.peerIsTyping);
                            }
                            safeApply(subscope);
                        });
                        subscope.$on("incoming", function(event, message, from, userid) {
                            if (from !== userid) {
                                subscope.pending++;
                                scope.$emit("chatincoming", subscope.id);
                            }
                            if (subscope.firstmessage || !desktopNotify.windowHasFocus) {
                                var room = event.targetScope.id;
                                // Make sure we are not in group chat or the message is from ourselves
                                // before we beep and shout.
                                if (!subscope.isgroupchat && from !== userid) {
                                    playSound.play("message1");
                                    desktopNotify.notify(translation._("Message from ")+displayName(from), message);
                                }
                                subscope.firstmessage = false;
                            }
                        });
                        chat(subscope, function(clonedElement, $scope) {

                            pane.append(clonedElement);
                            $scope.element=clonedElement;
                            $scope.visible = true;
                            if (options.autofocus) {
                                _.defer(function() {
                                    $scope.$broadcast("focus");
                                });
                            }

                            // Support drag and drop file uploads in Chat.
                            var namespace = "file_"+scope.id;
                            var binder = fileUpload.bindDrop(namespace, clonedElement, _.bind(function(files) {
                                console.log("File dragged", files);
                                _.each(files, _.bind(function(f) {
                                    var info = $.extend({id: f.id}, f.info);
                                    console.log("Advertising file", f, info);
                                    $scope.sendChat(subscope.id, "File", {FileInfo: info});
                                }, this));
                            }, this));
                            binder.namespace = function() {
                                // Inject own id into namespace.
                                return namespace+"_"+scope.myid;
                            };

                        });
                    } else {

                        if (options.restore) {
                            if (!subscope.visible) {
                                controller.visibleRooms.push(id);
                                subscope.index = index;
                                subscope.visible = true;
                            }
                        }
                        if (options.autofocus && subscope.visible) {
                            subscope.$broadcast("focus");
                        }

                    }

                    if (!options.noactivate) {
                        scope.activateRoom(subscope.id, true);
                    }

                    if (options.restore && !options.noenable) {
                        if (!scope.layout.chat) {
                            scope.layout.chat = true;
                        }
                    }

                    safeApply(subscope);
                    return subscope;
                };

                scope.hideRoom = function(id) {
                    var subscope = controller.rooms[id];
                    if (!subscope) {
                        console.log("hideRoom called for unknown room", id);
                        return;
                    }
                    var element = subscope.element;
                    var index = subscope.index;
                    controller.visibleRooms.splice(index, 1);
                    subscope.visible=false;
                    subscope.firstmessage=true;
                    // Refresh index of the rest of the rooms.
                    _.each(controller.visibleRooms, function(id, idx) {
                        var s = controller.rooms[id];
                        //console.log("updated idx", idx, s.index);
                        s.index = idx;
                    });
                    if (scope.currentRoom === subscope) {
                        scope.currentRoom = null;
                        scope.currentRoomActive = false;
                    }
                    if (!controller.visibleRooms.length) {
                        scope.showGroupRoom(null, {restore: true, noenable: true, noactivate: true});
                        // If last visible room was removed, hide chat.
                        scope.layout.chat = false;
                    }
                };

                scope.killRoom = function(id) {
                    scope.hideRoom(id);
                    var subscope = controller.rooms[id];
                    if (!subscope) {
                        return;
                    }
                    delete controller.rooms[id];
                    $timeout(function() {
                        subscope.$destroy();
                    }, 0);
                };

                scope.toggleMax = function() {
                    scope.layout.chatMaximized = !scope.layout.chatMaximized;
                };

                scope.activateRoom = function(id, active) {
                    var subscope = controller.rooms[id];
                    if (!subscope) {
                        return;
                    }
                    var visible = !!scope.layout.chat;
                    var flip = false;
                    //console.log("toggleActive", active, id, scope.currentRoom, scope.currentRoom == subscope, subscope.active);
                    if (scope.currentRoom == subscope) {
                        subscope.active = active;
                        scope.currentRoomActive = true;
                        if (visible) {
                            flip = true;
                        }
                    } else {
                        if (scope.currentRoom) {
                            scope.currentRoom.active = false;
                            //scope.currentRoom.hide();
                            if (visible) {
                                flip = true;
                            }
                        }
                        if (active) {
                            scope.currentRoom = subscope;
                            scope.currentRoomActive = true;
                        }
                        subscope.active = active;
                    }
                    if (flip) {
                        pane.toggleClass("flip");
                    }
                };

                scope.deactivateRoom = function() {
                    scope.currentRoomActive = false;
                };

                scope.$watch("layout.chat", function(chat) {
                    if (!chat) {
                        pane.removeClass("flip");
                    }
                    scope.layout.chatMaximized = false;
                });

                scope.$on("room", function(event, room) {
                    var subscope = scope.showGroupRoom(null, {restore: true, noenable: true, noactivate: true});
                    if (room) {
                        var msg = translation._("You are now in room %s ...", room);
                        subscope.$broadcast("display", null, $("<i><span>"+msg+"</span></i>"));
                    }
                });

            };

        };

        return {
            restrict: 'E',
            replace: true,
            scope: true,
            template: templateChat,
            controller: controller,
            compile: compile
        }

    }];

});
<commit_msg>Properly sanitize room names in chat.<commit_after>/*
 * Spreed Speak Freely.
 * Copyright (C) 2013-2014 struktur AG
 *
 * This file is part of Spreed Speak Freely.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'], function(_, templateChat, templateChatroom) {

    return ["$compile", "safeDisplayName", "mediaStream", "safeApply", "desktopNotify", "translation", "playSound", "fileUpload", "randomGen", "buddyData", "$timeout", "$sanitize", function($compile, safeDisplayName, mediaStream, safeApply, desktopNotify, translation, playSound, fileUpload, randomGen, buddyData, $timeout, $sanitize) {

        var displayName = safeDisplayName;
        var group_chat_id = "";

        var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {

            $scope.layout.chat = false;
            $scope.layout.chatMaximized = false;

            var ctrl = this;
            var rooms = ctrl.rooms = {};
            ctrl.visibleRooms = [];
            ctrl.group = group_chat_id;
            ctrl.get = function(id) {
                return ctrl.rooms[id];
            }

            $scope.currentRoom = null;
            $scope.currentRoomActive = false;
            $scope.getVisibleRooms = function() {
                var res = [];
                for (var i=0; i<ctrl.visibleRooms.length; i++) {
                    var r = rooms[ctrl.visibleRooms[i]];
                    if (!r || r.id === ctrl.group) {
                        continue;
                    }
                    res.push(r);
                }
                return res;
            };
            $scope.getGroupRoom = function() {
                return rooms[ctrl.group];
            };

            mediaStream.api.e.on("received.chat", function(event, id, from, data, p2p) {

                //console.log("received", data, id, from);

                var roomid = id;
                if (roomid === mediaStream.api.id) {
                    roomid = from;
                } else {
                    if (roomid !== ctrl.group && from !== mediaStream.api.id) {
                        console.log("Received chat message for invalid room", roomid, id, from);
                        return;
                    }
                }

                var with_message = !!data.Message;
                var room = rooms[roomid];
                if (!room) {
                    if (!with_message) {
                        return;
                    }
                    // No room with this id, get one with the from id
                    $scope.$emit("startchat", from, {restore: with_message});
                    room = rooms[from];
                }

                if (with_message && from !== mediaStream.api.id) {
                    room.newmessage = true;
                    room.peerIsTyping = "no";
                    room.p2p(!!p2p);
                }

                room.$broadcast("received", from, data);
                safeApply(room);

            });

            mediaStream.api.e.on("received.userleftorjoined", function(event, dataType, data) {
                var room = rooms[data.Id];
                if (room) {
                    switch (dataType) {
                    case "Left":
                        if (data.Status !== "soft") {
                            room.enabled = false;
                            room.$broadcast("received", data.Id, {Type: "LeftOrJoined", "LeftOrJoined": "left"});
                            safeApply(room);
                        }
                        break;
                    case "Joined":
                        if (!room.enabled) {
                            room.enabled = true;
                            _.delay(function() {
                                room.$broadcast("received", data.Id, {Type: "LeftOrJoined", "LeftOrJoined": "joined"});
                                safeApply(room);
                            }, 1000);
                        }
                        break;
                    default:
                        break;
                    }
                }
            });

            $scope.$parent.$on("startchat", function(event, id, options) {

                //console.log("startchat requested", event, id);
                if (id === group_chat_id) {
                    $scope.showGroupRoom(null, options);
                } else {
                    $scope.showRoom(id, {title: translation._("Chat with")}, options);
                }

            });

        }];

        var compile = function(tElement, tAttrs) {

            var chat = $compile(templateChatroom);
            return function(scope, iElement, iAttrs, controller) {

                var pane = iElement.find(".chatpane");

                scope.showGroupRoom = function(settings, options) {
                    var stngs = $.extend({title: translation._("Room chat")}, settings);
                    return scope.showRoom(controller.group, stngs, options);
                };

                scope.showRoom = function(id, settings, options) {
                    var options = $.extend({}, options);
                    var subscope = controller.rooms[id];
                    var index = controller.visibleRooms.length;
                    if (!subscope) {
                        console.log("Create new chatroom", [id]);
                        controller.visibleRooms.push(id);
                        subscope = controller.rooms[id] = scope.$new();
                        translation.inject(subscope);
                        subscope.id = id;
                        subscope.isgroupchat = id === controller.group ? true : false;
                        subscope.index = index;
                        subscope.settings = settings;
                        subscope.visible = false;
                        subscope.newmessage = false;
                        subscope.enabled = true;
                        subscope.peerIsTyping = "no";
                        subscope.firstmessage = true;
                        subscope.p2pstate = false;
                        subscope.active = false;
                        subscope.pending = 0;
                        if (!subscope.isgroupchat) {
                            buddyData.push(id);
                        }
                        subscope.hide = function() {
                            scope.hideRoom(id);
                        };
                        //TODO(longsleep): This is currently never called. Find a suitable way to clean up old chats.
                        subscope.kill = function() {
                            if (!subscope.isgroupchat) {
                                buddyData.pop(id);
                            }
                            scope.killRoom(id);
                        };
                        subscope.seen = function() {
                            subscope.pending = 0;
                            scope.$emit("chatseen", subscope.id);
                            if (subscope.newmessage) {
                                subscope.newmessage = false;
                                subscope.$broadcast("seen");
                            }
                        };
                        subscope.deactivate =function() {
                            scope.deactivateRoom();
                        };
                        subscope.toggleMax = function() {
                            scope.toggleMax();
                        };
                        subscope.sendChat = function(to, message, status, mid, noloop) {
                            //console.log("send chat", to, scope.peer);
                            var peercall = mediaStream.webrtc.findTargetCall(to);
                            if (message && !mid) {
                                mid = randomGen.random({hex: true});
                            };
                            if (peercall && peercall.peerconnection.datachannelReady) {
                                subscope.p2p(true);
                                // Send out stuff through data channel.
                                _.delay(function() {
                                    mediaStream.api.apply("sendChat", {
                                        send: function(type, data) {
                                            // We also send to self, to display our own stuff.
                                            if (!noloop) {
                                                mediaStream.api.received({Type: data.Type, Data: data, From: mediaStream.api.id, To: peercall.id});
                                            }
                                            return peercall.peerconnection.send(data);
                                        }
                                    })(to, message, status, mid);
                                }, 100);

                            } else {
                                subscope.p2p(false);
                                _.delay(function() {
                                    mediaStream.api.send2("sendChat", function(type, data) {
                                        if (!noloop) {
                                            //console.log("looped to self", type, data);
                                            mediaStream.api.received({Type: data.Type, Data: data, From: mediaStream.api.id, To: to});
                                        }
                                    })(to, message, status, mid);
                                }, 100);
                            }
                            return mid;
                        };
                        subscope.p2p = function(state) {
                            if (state !== subscope.p2pstate) {
                                subscope.p2pstate = state;
                                subscope.$broadcast("p2p", state);
                            }
                        };
                        //console.log("Creating new chat room", controller, subscope, index);
                        subscope.$on("submit", function(event, input) {
                            subscope.seen();
                            var mid = subscope.sendChat(event.targetScope.id, input);
                            event.targetScope.$broadcast("received", null, {Type: "Message", Status: {State: "sent", "Mid": mid}});
                        });
                        subscope.$on("submitseen", function(event, pending) {
                            //console.log("submitseen", pending);
                            subscope.sendChat(event.targetScope.id, null, {SeenMids: pending}, null, true);
                        });
                        subscope.$on("submitreceived", function(event, mid) {
                            subscope.sendChat(event.targetScope.id, null, {State: "delivered", Mid: mid}, null, true);
                        });
                        subscope.$on("typing", function(event, params) {
                            if (params.who === "local") {
                                var room = event.targetScope.id;
                                subscope.seen();
                                //console.log("typing event", params.status);
                                if (!subscope.isgroupchat) {
                                    // Transmit typing events to private chats.
                                    subscope.sendChat(event.targetScope.id, null, {Typing: params.status});
                                }
                            } else {
                                subscope.peerIsTyping = params.status;
                                //console.log("peer typing event", params.status, subscope.peerIsTyping);
                            }
                            safeApply(subscope);
                        });
                        subscope.$on("incoming", function(event, message, from, userid) {
                            if (from !== userid) {
                                subscope.pending++;
                                scope.$emit("chatincoming", subscope.id);
                            }
                            if (subscope.firstmessage || !desktopNotify.windowHasFocus) {
                                var room = event.targetScope.id;
                                // Make sure we are not in group chat or the message is from ourselves
                                // before we beep and shout.
                                if (!subscope.isgroupchat && from !== userid) {
                                    playSound.play("message1");
                                    desktopNotify.notify(translation._("Message from ")+displayName(from), message);
                                }
                                subscope.firstmessage = false;
                            }
                        });
                        chat(subscope, function(clonedElement, $scope) {

                            pane.append(clonedElement);
                            $scope.element=clonedElement;
                            $scope.visible = true;
                            if (options.autofocus) {
                                _.defer(function() {
                                    $scope.$broadcast("focus");
                                });
                            }

                            // Support drag and drop file uploads in Chat.
                            var namespace = "file_"+scope.id;
                            var binder = fileUpload.bindDrop(namespace, clonedElement, _.bind(function(files) {
                                console.log("File dragged", files);
                                _.each(files, _.bind(function(f) {
                                    var info = $.extend({id: f.id}, f.info);
                                    console.log("Advertising file", f, info);
                                    $scope.sendChat(subscope.id, "File", {FileInfo: info});
                                }, this));
                            }, this));
                            binder.namespace = function() {
                                // Inject own id into namespace.
                                return namespace+"_"+scope.myid;
                            };

                        });
                    } else {

                        if (options.restore) {
                            if (!subscope.visible) {
                                controller.visibleRooms.push(id);
                                subscope.index = index;
                                subscope.visible = true;
                            }
                        }
                        if (options.autofocus && subscope.visible) {
                            subscope.$broadcast("focus");
                        }

                    }

                    if (!options.noactivate) {
                        scope.activateRoom(subscope.id, true);
                    }

                    if (options.restore && !options.noenable) {
                        if (!scope.layout.chat) {
                            scope.layout.chat = true;
                        }
                    }

                    safeApply(subscope);
                    return subscope;
                };

                scope.hideRoom = function(id) {
                    var subscope = controller.rooms[id];
                    if (!subscope) {
                        console.log("hideRoom called for unknown room", id);
                        return;
                    }
                    var element = subscope.element;
                    var index = subscope.index;
                    controller.visibleRooms.splice(index, 1);
                    subscope.visible=false;
                    subscope.firstmessage=true;
                    // Refresh index of the rest of the rooms.
                    _.each(controller.visibleRooms, function(id, idx) {
                        var s = controller.rooms[id];
                        //console.log("updated idx", idx, s.index);
                        s.index = idx;
                    });
                    if (scope.currentRoom === subscope) {
                        scope.currentRoom = null;
                        scope.currentRoomActive = false;
                    }
                    if (!controller.visibleRooms.length) {
                        scope.showGroupRoom(null, {restore: true, noenable: true, noactivate: true});
                        // If last visible room was removed, hide chat.
                        scope.layout.chat = false;
                    }
                };

                scope.killRoom = function(id) {
                    scope.hideRoom(id);
                    var subscope = controller.rooms[id];
                    if (!subscope) {
                        return;
                    }
                    delete controller.rooms[id];
                    $timeout(function() {
                        subscope.$destroy();
                    }, 0);
                };

                scope.toggleMax = function() {
                    scope.layout.chatMaximized = !scope.layout.chatMaximized;
                };

                scope.activateRoom = function(id, active) {
                    var subscope = controller.rooms[id];
                    if (!subscope) {
                        return;
                    }
                    var visible = !!scope.layout.chat;
                    var flip = false;
                    //console.log("toggleActive", active, id, scope.currentRoom, scope.currentRoom == subscope, subscope.active);
                    if (scope.currentRoom == subscope) {
                        subscope.active = active;
                        scope.currentRoomActive = true;
                        if (visible) {
                            flip = true;
                        }
                    } else {
                        if (scope.currentRoom) {
                            scope.currentRoom.active = false;
                            //scope.currentRoom.hide();
                            if (visible) {
                                flip = true;
                            }
                        }
                        if (active) {
                            scope.currentRoom = subscope;
                            scope.currentRoomActive = true;
                        }
                        subscope.active = active;
                    }
                    if (flip) {
                        pane.toggleClass("flip");
                    }
                };

                scope.deactivateRoom = function() {
                    scope.currentRoomActive = false;
                };

                scope.$watch("layout.chat", function(chat) {
                    if (!chat) {
                        pane.removeClass("flip");
                    }
                    scope.layout.chatMaximized = false;
                });

                scope.$on("room", function(event, room) {
                    var subscope = scope.showGroupRoom(null, {restore: true, noenable: true, noactivate: true});
                    if (room) {
                        var msg = translation._("You are now in room %s ...", $sanitize(room));
                        subscope.$broadcast("display", null, $("<i><span>"+msg+"</span></i>"));
                    }
                });

            };

        };

        return {
            restrict: 'E',
            replace: true,
            scope: true,
            template: templateChat,
            controller: controller,
            compile: compile
        }

    }];

});
<|endoftext|>


<commit_before>angular.module('auction')
  .factory('AuctionUtils', ['$filter', '$timeout', function($filter, $timeout) {
    // Format msg for timer
    function timer_message(auction, bidder) {
      // if (auction.current_stage < 0) {
      //   // * until the auction starts
      //   return "until the auction starts"
      // }else if(auction.current_stage == (auction.stages.length - 1)){
      //   return "after the auction was completed"
      // }else if(auction.stages[auction.current_stage].type = 'pause'){
      //   return "until the round starts"
      // };
      // * until your turn
      // * until your turn ends
      // * until the round ends
      // * until the results announcement
      // * after the auction was completed
      return ""
    };
    // Get bidder_id from query
    function get_bidder_id() {
        var query = window.location.search.substring(1);
        var vars = query.split('&');
        for (var i = 0; i < vars.length; i++) {
          var pair = vars[i].split('=');
          if (decodeURIComponent(pair[0]) == 'bidder_id') {
            return decodeURIComponent(pair[1]);
          }
        }
      }
      // Format date with traslations
    function format_date(date, format) {
      return $filter('date')(date, $filter('translate')(format));
    };

    // Get round data
    function get_round_data(pause_index, auction_doc, Rounds) {
      if (pause_index <= Rounds[0]) {
        return {
          'type': 'pause',
          'data': ['', '1', ]
        }
      }
      for (var i in Rounds) {
        if (pause_index < Rounds[i]) {
          return {
            'type': 'round',
            'data': parseInt(i)
          }
        } else if ((pause_index == Rounds[i]) && (pause_index != auction_doc.stages.length - 1)) {
          return {
            'type': 'pause',
            'data': [(parseInt(i)).toString(), (parseInt(i)+1).toString(), ]
          }
        }
      };
      return {
        'type': 'finish'
      }
    }
    // Scroll functionality
    function scroll_to_stage (stage) {
      $timeout(function() {
        var stage_el = document.getElementById('stage-' + stage.toString())
        if (stage_el) {
          window.scrollBy(0, stage_el.getBoundingClientRect().top);
          window.scrollBy(0, -100);
        }
      }, 500);
    }
    return {
      'timer_message': timer_message,
      'get_bidder_id': get_bidder_id,
      'format_date': format_date,
      'get_round_data': get_round_data,
      'scroll_to_stage': scroll_to_stage
    }
  }]);<commit_msg>Fixed round text<commit_after>angular.module('auction')
  .factory('AuctionUtils', ['$filter', '$timeout', function($filter, $timeout) {
    // Format msg for timer
    function timer_message(auction, bidder) {
      // if (auction.current_stage < 0) {
      //   // * until the auction starts
      //   return "until the auction starts"
      // }else if(auction.current_stage == (auction.stages.length - 1)){
      //   return "after the auction was completed"
      // }else if(auction.stages[auction.current_stage].type = 'pause'){
      //   return "until the round starts"
      // };
      // * until your turn
      // * until your turn ends
      // * until the round ends
      // * until the results announcement
      // * after the auction was completed
      return ""
    };
    // Get bidder_id from query
    function get_bidder_id() {
        var query = window.location.search.substring(1);
        var vars = query.split('&');
        for (var i = 0; i < vars.length; i++) {
          var pair = vars[i].split('=');
          if (decodeURIComponent(pair[0]) == 'bidder_id') {
            return decodeURIComponent(pair[1]);
          }
        }
      }
      // Format date with traslations
    function format_date(date, format) {
      return $filter('date')(date, $filter('translate')(format));
    };

    // Get round data
    function get_round_data(pause_index, auction_doc, Rounds) {
      if (pause_index <= Rounds[0]) {
        return {
          'type': 'pause',
          'data': ['', '1', ]
        }
      }
      for (var i in Rounds) {
        if (pause_index < Rounds[i]) {
          return {
            'type': 'round',
            'data': parseInt(i)
          }
        } else if (pause_index == Rounds[i]) {
          return {
            'type': 'pause',
            'data': [(parseInt(i)).toString(), (parseInt(i)+1).toString(), ]
          }
        }
      };

      if (pause_index < (auction_doc.stages.length - 1)) {
        return {
          'type': 'round',
          'data': Rounds.length
        }
      } else {
        return {
          'type': 'finish'
        }
      }
    }
    // Scroll functionality
    function scroll_to_stage (stage) {
      $timeout(function() {
        var stage_el = document.getElementById('stage-' + stage.toString())
        if (stage_el) {
          window.scrollBy(0, stage_el.getBoundingClientRect().top);
          window.scrollBy(0, -100);
        }
      }, 500);
    }
    return {
      'timer_message': timer_message,
      'get_bidder_id': get_bidder_id,
      'format_date': format_date,
      'get_round_data': get_round_data,
      'scroll_to_stage': scroll_to_stage
    }
  }]);<|endoftext|>


<commit_before>jQuery(function($){
    $(document).ready(function(){
        _p = jarn.i18n.MessageFactory('plone');
        _ = jarn.i18n.MessageFactory('bika');

        function recordswidget_lookups(elements){
            if(elements == undefined){
                var inputs = $("[combogrid_options]");
            } else {
                var inputs = elements;
            }
            for (var i = inputs.length - 1; i >= 0; i--) {
                var element = inputs[i];
                var options = $.parseJSON($(element).attr('combogrid_options'));
                if(options == '' || options == undefined || options == null){
                    continue;
                }
                options.select = function(event, ui){
                    event.preventDefault();
                    // Set value in activated element (must exist in colModel!)
                    var fieldName = $(this).attr('name').split(".")[0];
                    var key = $(this).attr('name').split(".")[1].split(":")[0];
                    row_nr = parseInt(this.id.split("-")[2]);
                    $(this).val(ui.item[key]);
                    // Set values if colModel matches recordswidget subfield name
                    var colModel = $.parseJSON($(this).attr('combogrid_options')).colModel;
                    for (var i = colModel.length - 1; i >= 0; i--) {
                        var colname = colModel[i]['columnName'];
                        if (colname != key) {
                            var element = $('#'+fieldName+'-'+colname+'-'+row_nr);
                            if(element.length == 1){
                                $(element).val(ui.item[colname]);
                            }
                        }
                    }
                }
                if(window.location.href.search("portal_factory") > -1){
                    options.url = window.location.href.split("/portal_factory")[0] + "/" + options.url;
                }
                options.url = options.url + '?_authenticator=' + $('input[name="_authenticator"]').val();
                $(element).combogrid(options);
            };
        }
        recordswidget_lookups();

        $('[combogrid_options]').live('focus', function(){
            // For inputs with combogrids, we want them to clear when focused
            $(this).val('');
            // We also want to clear all colModel->subfield completions
            var options = $.parseJSON($(this).attr('combogrid_options'));
            if(options != '' && options != undefined && options != null){
                var fieldName = $(this).attr('name').split(".")[0];
                var key = $(this).attr('name').split(".")[1].split(":")[0];
                var colModel = $.parseJSON($(this).attr('combogrid_options')).colModel;
                row_nr = parseInt(this.id.split("-")[2]);
                for (var i = colModel.length - 1; i >= 0; i--) {
                    var colname = colModel[i]['columnName'];
                    if (colname != key) {
                        var element = $('#'+fieldName+'-'+colname+'-'+row_nr);
                        if(element.length == 1){
                            $(element).val('');
                        }
                    }
                }
            }
        });

        $("input[id$='_more']").click(function(i,e){
            var fieldname = $(this).attr("id").split("_")[0];
            var table = $('#'+fieldname+"_table");
            var rows = $(".records_row_"+fieldname);
            // clone last row
            var row = $(rows[rows.length-1]).clone();
            // after cloning, make sure the new element's IDs are unique
            var found = $(row).find('input[id^='+fieldname+']');
            for (var i = found.length - 1; i >= 0; i--) {
                var ID = found[i].id;
                var prefix = ID.split("-")[0] + "-" + ID.split("-")[1];
                var nr = parseInt(ID.split("-")[2]) + 1;
                $(found[i]).attr('id', prefix + "-" + nr);
            };
            // First check to see that all required subfields are completed,
            // before allowing a new row to be added
            for (var i = found.length - 1; i >= 0; i--) {
                var e = found[i];
                var required = $(e).hasClass('required');
                var val = $(e).val();
                if (required && val == ""){
                    window.bika_utils.portalMessage(e.id.split("-")[1] + ": " + _p("Input is required but not given."));
                    return false;
                }
            };
            // clear values
            for(i=0; i<$(row).children().length; i++){
                var td = $(row).children()[i];
                var input = $(td).children()[0];
                $(input).val('');
            }
            $(row).appendTo($(table));
            recordswidget_lookups($(row).find('[combogrid_options]'));
        });

        $(".rw_deletebtn").live('click', function(i,e){
            var row = $(this).parent().parent();
            var siblings = $(row).siblings();
            if (siblings.length < 2) return;
            $(this).parent().parent().remove();
        });

    });
});
<commit_msg>RecordsWidget: don't clear inputs that don't actually have combogrid lookup widgets attached<commit_after>jQuery(function($){
    $(document).ready(function(){
        _p = jarn.i18n.MessageFactory('plone');
        _ = jarn.i18n.MessageFactory('bika');

        function recordswidget_lookups(elements){
            if(elements == undefined){
                var inputs = $("[combogrid_options]");
            } else {
                var inputs = elements;
            }
            for (var i = inputs.length - 1; i >= 0; i--) {
                var element = inputs[i];
                var options = $.parseJSON($(element).attr('combogrid_options'));
                if(options == '' || options == undefined || options == null){
                    continue;
                }
                options.select = function(event, ui){
                    event.preventDefault();
                    // Set value in activated element (must exist in colModel!)
                    var fieldName = $(this).attr('name').split(".")[0];
                    var key = $(this).attr('name').split(".")[1].split(":")[0];
                    row_nr = parseInt(this.id.split("-")[2]);
                    $(this).val(ui.item[key]);
                    // Set values if colModel matches recordswidget subfield name
                    var colModel = $.parseJSON($(this).attr('combogrid_options')).colModel;
                    for (var i = colModel.length - 1; i >= 0; i--) {
                        var colname = colModel[i]['columnName'];
                        if (colname != key) {
                            var element = $('#'+fieldName+'-'+colname+'-'+row_nr);
                            if(element.length == 1){
                                $(element).val(ui.item[colname]);
                            }
                        }
                    }
                }
                if(window.location.href.search("portal_factory") > -1){
                    options.url = window.location.href.split("/portal_factory")[0] + "/" + options.url;
                }
                options.url = options.url + '?_authenticator=' + $('input[name="_authenticator"]').val();
                $(element).combogrid(options);
            };
        }
        recordswidget_lookups();

        $('[combogrid_options]').live('focus', function(){
            cgo = $(this).attr('combogrid_options');
            if(cgo==''){
                return;
            }
            // For inputs with combogrids, we want them to clear when focused
            $(this).val('');
            // We also want to clear all colModel->subfield completions
            var options = $.parseJSON($(this).attr('combogrid_options'));
            if(options != '' && options != undefined && options != null){
                var fieldName = $(this).attr('name').split(".")[0];
                var key = $(this).attr('name').split(".")[1].split(":")[0];
                var colModel = $.parseJSON($(this).attr('combogrid_options')).colModel;
                row_nr = parseInt(this.id.split("-")[2]);
                for (var i = colModel.length - 1; i >= 0; i--) {
                    var colname = colModel[i]['columnName'];
                    if (colname != key) {
                        var element = $('#'+fieldName+'-'+colname+'-'+row_nr);
                        if(element.length == 1){
                            $(element).val('');
                        }
                    }
                }
            }
        });

        $("input[id$='_more']").click(function(i,e){
            var fieldname = $(this).attr("id").split("_")[0];
            var table = $('#'+fieldname+"_table");
            var rows = $(".records_row_"+fieldname);
            // clone last row
            var row = $(rows[rows.length-1]).clone();
            // after cloning, make sure the new element's IDs are unique
            var found = $(row).find('input[id^='+fieldname+']');
            for (var i = found.length - 1; i >= 0; i--) {
                var ID = found[i].id;
                var prefix = ID.split("-")[0] + "-" + ID.split("-")[1];
                var nr = parseInt(ID.split("-")[2]) + 1;
                $(found[i]).attr('id', prefix + "-" + nr);
            };
            // First check to see that all required subfields are completed,
            // before allowing a new row to be added
            for (var i = found.length - 1; i >= 0; i--) {
                var e = found[i];
                var required = $(e).hasClass('required');
                var val = $(e).val();
                if (required && val == ""){
                    window.bika_utils.portalMessage(e.id.split("-")[1] + ": " + _p("Input is required but not given."));
                    return false;
                }
            };
            // clear values
            for(i=0; i<$(row).children().length; i++){
                var td = $(row).children()[i];
                var input = $(td).children()[0];
                $(input).val('');
            }
            $(row).appendTo($(table));
            recordswidget_lookups($(row).find('[combogrid_options]'));
        });

        $(".rw_deletebtn").live('click', function(i,e){
            var row = $(this).parent().parent();
            var siblings = $(row).siblings();
            if (siblings.length < 2) return;
            $(this).parent().parent().remove();
        });

    });
});
<|endoftext|>


<commit_before>var UNDO_ELEMENT = document.getElementById('undoElement');
var STAT_SCROLLER = document.getElementById('statScroller');
var PLAYERS = document.getElementById('meta_players').getAttribute('content');
var PLAYERCOLORS = ['red', 'blue', 'teal', 'orange'];
var LOW_HEALTH = 10;

var undoHistory = [];
var endGameTriggered = false;

window.mobileAndTabletcheck = function() {
  var check = false;
  (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
  return check;
};
var IS_MOBILE = window.mobileAndTabletcheck();

if (IS_MOBILE) {
  document.ontouchmove = function(event) {
    event.preventDefault();
  };
}

if (IS_MOBILE) {
  UNDO_ELEMENT.addEventListener('touchstart', function() {
    popUndo();
  });
} else {
  document.onkeydown = function(e) {
    var evtobj = window.event? event : e;
    if (evtobj.keyCode == 90 && evtobj.ctrlKey) popUndo();
    if (evtobj.keyCode == 13) endGame();
  };
}

for (var statElement of document.getElementsByTagName('stat-component')) {
  statElement.init(IS_MOBILE);
  statElement.setAttribute('value-change', 'valueChange');
}

function valueChange(element, diff) { // eslint-disable-line no-unused-vars
  if (diff == 0) return;
  lowHealth(element);
  var amount = Math.abs(diff);
  var player = element.getAttribute('player');
  var commander = element.getAttribute('commander');
  if (commander != null) {
    var lifeElement = document.querySelector(`.life[player="${player}"]`);
    lifeElement.innerHTML = Number(lifeElement.innerHTML) - diff;
    STAT_SCROLLER.addStat(player, amount, '', commander);
    pushUndo([
      element,
      lifeElement
    ], [
      Number(element.innerHTML) - diff,
      Number(lifeElement.innerHTML) + diff
    ]);
  } else if (element.classList.contains('infect')) {
    STAT_SCROLLER.addStat(player, amount, 'infect');
    pushUndo([element], [Number(element.innerHTML) - diff]);
  } else {
    var type = (diff > 0) ? 'heal' : '';
    STAT_SCROLLER.addStat(player, amount, type);
    pushUndo([element], [Number(element.innerHTML) - diff]);
  }
}

function pushUndo(elements, amounts) {
  undoHistory.push({'elements': elements, 'amounts': amounts});
}

function popUndo() {
  var undoObject = undoHistory.pop();
  if (undoObject) {
    for (var i = 0; i < undoObject.elements.length; i++) {
      undoObject.elements[i].innerHTML = undoObject.amounts[i];
      lowHealth(undoObject.elements[i]);
    }
    if (undoHistory.length === 0) {
      UNDO_ELEMENT.style.display = 'none';
    }
    STAT_SCROLLER.removeStat();
  }
}

function lowHealth(lifeElement) {
  var health = Number(lifeElement.innerHTML);
  if (health <= LOW_HEALTH) {
    lifeElement.setAttribute('lowHealth', 'true');
  } else {
    lifeElement.removeAttribute('lowHealth');
  }
}

function endGame() {
  if (endGameTriggered === true) {
    return;
  }
  endGameTriggered = true;
  var playerNames = [];
  for (var i = 0; i < PLAYERS; i++) {
    playerNames[i] = prompt('Player ' + PLAYERCOLORS[i] + ' name?', PLAYERCOLORS[i]);
    if (playerNames[i] === null) {
      endGameTriggered = false;
      return;
    }
  }
  var winner = prompt('Winner? (0-' + (PLAYERS - 1) + ')', '0');
  if (winner === null) return;
  winner = Number(winner);
  var matches = localStorage.getItem('matches');
  if (matches === null) {
    matches = '[]';
  }
  matches = JSON.parse(matches);
  matches.push({
    "players": playerNames,
    "winner": winner
  });
  var matchesString = JSON.stringify(matches);
  localStorage.setItem('matches', matchesString);
  window.location.href = 'history.html';
}
<commit_msg>Fixed hidden undo element on mobile.<commit_after>var UNDO_ELEMENT = document.getElementById('undoElement');
var STAT_SCROLLER = document.getElementById('statScroller');
var PLAYERS = document.getElementById('meta_players').getAttribute('content');
var PLAYERCOLORS = ['red', 'blue', 'teal', 'orange'];
var LOW_HEALTH = 10;

var undoHistory = [];
var endGameTriggered = false;

window.mobileAndTabletcheck = function() {
  var check = false;
  (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
  return check;
};
var IS_MOBILE = window.mobileAndTabletcheck();

if (IS_MOBILE) {
  document.ontouchmove = function(event) {
    event.preventDefault();
  };
}

if (IS_MOBILE) {
  UNDO_ELEMENT.addEventListener('touchstart', function() {
    popUndo();
  });
} else {
  document.onkeydown = function(e) {
    var evtobj = window.event? event : e;
    if (evtobj.keyCode == 90 && evtobj.ctrlKey) popUndo();
    if (evtobj.keyCode == 13) endGame();
  };
}

for (var statElement of document.getElementsByTagName('stat-component')) {
  statElement.init(IS_MOBILE);
  statElement.setAttribute('value-change', 'valueChange');
}

function valueChange(element, diff) { // eslint-disable-line no-unused-vars
  if (diff == 0) return;
  lowHealth(element);
  var amount = Math.abs(diff);
  var player = element.getAttribute('player');
  var commander = element.getAttribute('commander');
  if (commander != null) {
    var lifeElement = document.querySelector(`.life[player="${player}"]`);
    lifeElement.innerHTML = Number(lifeElement.innerHTML) - diff;
    STAT_SCROLLER.addStat(player, amount, '', commander);
    pushUndo([
      element,
      lifeElement
    ], [
      Number(element.innerHTML) - diff,
      Number(lifeElement.innerHTML) + diff
    ]);
  } else if (element.classList.contains('infect')) {
    STAT_SCROLLER.addStat(player, amount, 'infect');
    pushUndo([element], [Number(element.innerHTML) - diff]);
  } else {
    var type = (diff > 0) ? 'heal' : '';
    STAT_SCROLLER.addStat(player, amount, type);
    pushUndo([element], [Number(element.innerHTML) - diff]);
  }
}

function pushUndo(elements, amounts) {
  undoHistory.push({'elements': elements, 'amounts': amounts});
  if (IS_MOBILE) {
    UNDO_ELEMENT.style.display = '';
  }
}

function popUndo() {
  var undoObject = undoHistory.pop();
  if (undoObject) {
    for (var i = 0; i < undoObject.elements.length; i++) {
      undoObject.elements[i].innerHTML = undoObject.amounts[i];
      lowHealth(undoObject.elements[i]);
    }
    if (undoHistory.length === 0) {
      UNDO_ELEMENT.style.display = 'none';
    }
    STAT_SCROLLER.removeStat();
  }
}

function lowHealth(lifeElement) {
  var health = Number(lifeElement.innerHTML);
  if (health <= LOW_HEALTH) {
    lifeElement.setAttribute('lowHealth', 'true');
  } else {
    lifeElement.removeAttribute('lowHealth');
  }
}

function endGame() {
  if (endGameTriggered === true) {
    return;
  }
  endGameTriggered = true;
  var playerNames = [];
  for (var i = 0; i < PLAYERS; i++) {
    playerNames[i] = prompt('Player ' + PLAYERCOLORS[i] + ' name?', PLAYERCOLORS[i]);
    if (playerNames[i] === null) {
      endGameTriggered = false;
      return;
    }
  }
  var winner = prompt('Winner? (0-' + (PLAYERS - 1) + ')', '0');
  if (winner === null) return;
  winner = Number(winner);
  var matches = localStorage.getItem('matches');
  if (matches === null) {
    matches = '[]';
  }
  matches = JSON.parse(matches);
  matches.push({
    "players": playerNames,
    "winner": winner
  });
  var matchesString = JSON.stringify(matches);
  localStorage.setItem('matches', matchesString);
  window.location.href = 'history.html';
}
<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes",
  "Merging in private branch",
  "Time machines are real man!"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 10% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.1;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['ad<commit_msg>AAAAAAAAAAARGH!<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes",
  "Merging in private branch",
  "Time machines are real man!"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 10% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.1;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } <|endoftext|>


<commit_before>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

//CREATE WELCOME TEXT
var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 8 )
{
  groet = "Goeiemorgen 🌝.  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
else
if ( myDate.getHours() >8 )
{
  groet = "Goeiemorgen 🌝 ";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag 🌞";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17&& myDate.getHours() <= 20 )
{
groet = "Goedenavond 🌙";
}
else
if (myDate.getHours() > 20  || myDate.getHours() <= 24 )
{
  groet = "Goedenavond 🌙  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom. ";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}... Wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`![](http://www.bieg.nl/beeld/woningen.jpg)`))
        .then(() => bot.say(`%[Starters Hypotheek](postback:hypotheektype_starter)`))
        .then(() => bot.say (`%[Nieuwe hypotheek](postback:hypotheektype_nieuw) `))
        .then(() => bot.say (`%[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'speak');
    }
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim();

              function updateSilent() {
                  switch (upperText) {
                      //THE MORTGAGE STUFF
                      case 'Hoi':
                            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
                            .then(() => 'askName')
                          break;
                      case 'Starters Hypotheek':
                          return bot.say(`Wat voor type woning zoek je? `)
                          .then(() => bot.say(`%[🏬 Appartement](postback:hypotheekkeuze_appartement) %[🏠 Huis](postback:hypotheekkeuze_huis) %[📭 Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
                          .then(() => 'woningType')
                              break;
                      case 'Nieuwe hypotheek':
                          return bot.say(`😞 Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
                          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[💼 Zoek Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/jelocatie.aspx)`))
                            .then(() => 'finish')
                          break;
                      case 'Hypotheek oversluiten':
                          return bot.say(`😟 Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
                          .then(()=> bot.say(`Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja, dat wil ik wel](postback:update_ja) %[Nee, dat hoeft niet](postback:update_nee)`))
                            .then(() => 'updateOntvangen')
                          break;
                      //THE REST
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              //CHECK INPUT  FLOW
              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  //BASICALLY ERROR OR NO TXT
                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`![](http://www.bieg.nl/beeld/speechbubble.gif)`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<commit_msg>dq<commit_after>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

//CREATE WELCOME TEXT
var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 8 )
{
  groet = "Goeiemorgen 🌝.  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
else
if ( myDate.getHours() >8 )
{
  groet = "Goeiemorgen 🌝 ";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag 🌞";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17&& myDate.getHours() <= 20 )
{
groet = "Goedenavond 🌙";
}
else
if (myDate.getHours() > 20  || myDate.getHours() <= 24 )
{
  groet = "Goedenavond 🌙  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom. ";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}... Wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`![](http://www.bieg.nl/beeld/woningen.jpg)`))
        .then(() => bot.say(`%[Starters Hypotheek](postback:hypotheektype_starter)`))
        .then(() => bot.say (`%[Nieuwe hypotheek](postback:hypotheektype_nieuw) `))
        .then(() => bot.say (`%[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'speak');
    }
},

  speak: {
          receive: (bot, message) => {

              const upperText = message.text.trim();

              function updateSilent() {
                  switch (upperText) {
                      //THE MORTGAGE STUFF
                      case 'Hoi':
                            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
                            .then(() => 'askName')
                          break;
                      case 'Starters Hypotheek':
                          return bot.say(`Wat voor type woning zoek je? `)
                          .then(() => bot.say(`%[🏬 Appartement](postback:hypotheekkeuze_appartement) %[🏠 Huis](postback:hypotheekkeuze_huis) %[📭 Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
                          .then(() => 'woningType')
                              break;
                      case 'Nieuwe hypotheek':
                          return bot.say(`😞 Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
                          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[💼 Zoek Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/jelocatie.aspx)`))
                            .then(() => 'finish')
                          break;
                      case 'Hypotheek oversluiten':
                          return bot.say(`😟 Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
                          .then(()=> bot.say(`Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja, dat wil ik wel](postback:update_ja) %[Nee, dat hoeft niet](postback:update_nee)`))
                            .then(() => 'updateOntvangen')
                          break;
                      //THE REST
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              //CHECK INPUT  FLOW
              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  //BASICALLY ERROR OR NO TXT
                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`![](http://www.bieg.nl/beeld/speechbubble.gif)`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<|endoftext|>


<commit_before>$(document).ready(function () {

    var str = "";
    //declare the number of blocks of the game
    var blocks = 100;
    //declare the number of mines in the game
    var numberOfMines = 10;
    //no. of blocks per row
    var numberOfBlocksPerRow = 10;
    //deduce the number of rows
    var numberOfRows = Math.ceil(blocks / numberOfBlocksPerRow);
    //The array which stores the locations of the mine
    var mineMap = [];
    var playerMineMap = [];
    var init = function () {
        str="";mineMap=[];playerMineMap=[];
        $("#mode").removeClass("flag").addClass("mine")
        for (var i = 0; i < numberOfRows; i++) {
            str += '
';
            for (var j = 1; j <= numberOfBlocksPerRow; j++) {
                if (((i * numberOfBlocksPerRow) + j) <= blocks) {
                    str += '

';
                }

            }
            str += '
';
        }
        $("#colosseum").html(str+"

");
        setMines();
    }

    var setMines = function () {

       /*place the mine randomly in tiles*/
        while (mineMap.length<numberOfMines) {
            var randomnumber = (Math.ceil(Math.random() * blocks));
            var found = false;
            for (var j = 0; j < mineMap.length; j++) {
                if (mineMap[j] == randomnumber) {
                    found = true;
                    break
                }
            }
            if (!found) {
                mineMap.push(randomnumber);

            }
        }

    }

    var checkForMines = function(tileSiblings) {
            /*check for mines in the sibling tiles*/
            var mineCount = 0;

            for(var tile in tileSiblings)
            {
                var tileLocation = parseInt(tileSiblings[tile].attr("location"));
                var matchedMineLocation = mineMap.indexOf(tileLocation);
                if(matchedMineLocation!==-1)
                {
                    mineCount++;
                    $(this).html(mineCount);

                }

            }

            if(!mineCount){
                /*if no mines found then make the tiles inactive*/
                 for(var tile in tileSiblings)
                 {
                     if(tileSiblings[tile].length)
                     {
                        //tileSiblings[tile].html(0)
                        tileSiblings[tile].removeClass("active").addClass("inactive");

                           /*call the function recursively*/
                        if(tile !== "currentTile")
                        {
                            findMines.call(tileSiblings[tile]);
                        }

                     }

                 }

            }

            }

    var mapSiblingTiles = function (location,currentTray,topTray,bottomTray)
    {
        /*get the sibling tiles of the tile clicked currently*/
        var tileSiblings = {};
        if(topTray.length)
        {
            tileSiblings.topLefttile = topTray.find(".active[location="+(parseInt(location)-parseInt(numberOfBlocksPerRow)-1)+"]");
            tileSiblings.topCentretile = topTray.find(".active[location="+(parseInt(location)-parseInt(numberOfBlocksPerRow))+"]");
            tileSiblings.topRighttile = topTray.find(".active[location="+(parseInt(location)-parseInt(numberOfBlocksPerRow)+1)+"]");

        }
            tileSiblings.centreLefttile = currentTray.find(".active[location="+(parseInt(location)-1)+"]");
            tileSiblings.currentTile = currentTray.find(".active[location="+(parseInt(location))+"]");
            tileSiblings.centreRighttile = currentTray.find(".active[location="+(parseInt(location)+1)+"]");

        if(bottomTray.length)
        {
            tileSiblings.bottomLefttile = bottomTray.find(".active[location="+(parseInt(location)+parseInt(numberOfBlocksPerRow)-1)+"]");
            tileSiblings.bottomCentretile = bottomTray.find(".active[location="+(parseInt(location)+parseInt(numberOfBlocksPerRow))+"]");
            tileSiblings.bottomRighttile = bottomTray.find(".active[location="+(parseInt(location)+parseInt(numberOfBlocksPerRow+1))+"]");
        }
       /*check for mines in the sibling tiles*/
      checkForMines.call(this,tileSiblings);

    }

    var findMines = function()
    {

            /*check if te player has clicked on mine*/
            if(mineMap.indexOf(parseInt($(this).attr("location"))) === -1 )
            {
                var location = $(this).attr("location");
                var currentTray = $(this).closest(".tray");
                var topTray = currentTray.prev(".tray");
                var bottomTray = currentTray.next(".tray");
                mapSiblingTiles.call(this,location,currentTray,topTray,bottomTray,this);
            }
            else
            {
                $(this).addClass("mine");
                alert("gameover");
                init();
            }

    };
    var allMinesIdentified = function()
    {
        playerMineMap.push(parseInt($(this).attr("location")));
        if($(playerMineMap).not(mineMap).length == 0 && $(mineMap).not(playerMineMap).length == 0)
        {
            alert("You Win");
            init();
        }
    };
    var flagMine = function()
    {
        $(this).toggleClass("flag");
        allMinesIdentified.call(this);

    }
    var checkMode = function()
    {

        if($("#mode").hasClass("mine"))
        {
            findMines.call(this);
        }
        else
        {
            flagMine.call(this);
        }
    };

    var setMode = function()
    {
       $(this).toggleClass("mine flag");
    }
    /*Event handler for user's click on the tile*/
    $("#colosseum").on("click",".tile.active",checkMode);
    $("#mode").on("click",setMode);
    init();

});<commit_msg>change mine count<commit_after>$(document).ready(function () {

    var str = "";
    //declare the number of blocks of the game
    var blocks = 100;
    //declare the number of mines in the game
    var numberOfMines = 2;
    //no. of blocks per row
    var numberOfBlocksPerRow = 10;
    //deduce the number of rows
    var numberOfRows = Math.ceil(blocks / numberOfBlocksPerRow);
    //The array which stores the locations of the mine
    var mineMap = [];
    var playerMineMap = [];
    var init = function () {
        str="";mineMap=[];playerMineMap=[];
        $("#mode").removeClass("flag").addClass("mine")
        for (var i = 0; i < numberOfRows; i++) {
            str += '
';
            for (var j = 1; j <= numberOfBlocksPerRow; j++) {
                if (((i * numberOfBlocksPerRow) + j) <= blocks) {
                    str += '

';
                }

            }
            str += '
';
        }
        $("#colosseum").html(str+"

");
        setMines();
    }

    var setMines = function () {

       /*place the mine randomly in tiles*/
        while (mineMap.length<numberOfMines) {
            var randomnumber = (Math.ceil(Math.random() * blocks));
            var found = false;
            for (var j = 0; j < mineMap.length; j++) {
                if (mineMap[j] == randomnumber) {
                    found = true;
                    break
                }
            }
            if (!found) {
                mineMap.push(randomnumber);

            }
        }

    }

    var checkForMines = function(tileSiblings) {
            /*check for mines in the sibling tiles*/
            var mineCount = 0;

            for(var tile in tileSiblings)
            {
                var tileLocation = parseInt(tileSiblings[tile].attr("location"));
                var matchedMineLocation = mineMap.indexOf(tileLocation);
                if(matchedMineLocation!==-1)
                {
                    mineCount++;
                    $(this).html(mineCount);

                }

            }

            if(!mineCount){
                /*if no mines found then make the tiles inactive*/
                 for(var tile in tileSiblings)
                 {
                     if(tileSiblings[tile].length)
                     {
                        //tileSiblings[tile].html(0)
                        tileSiblings[tile].removeClass("active").addClass("inactive");

                           /*call the function recursively*/
                        if(tile !== "currentTile")
                        {
                            findMines.call(tileSiblings[tile]);
                        }

                     }

                 }

            }

            }

    var mapSiblingTiles = function (location,currentTray,topTray,bottomTray)
    {
        /*get the sibling tiles of the tile clicked currently*/
        var tileSiblings = {};
        if(topTray.length)
        {
            tileSiblings.topLefttile = topTray.find(".active[location="+(parseInt(location)-parseInt(numberOfBlocksPerRow)-1)+"]");
            tileSiblings.topCentretile = topTray.find(".active[location="+(parseInt(location)-parseInt(numberOfBlocksPerRow))+"]");
            tileSiblings.topRighttile = topTray.find(".active[location="+(parseInt(location)-parseInt(numberOfBlocksPerRow)+1)+"]");

        }
            tileSiblings.centreLefttile = currentTray.find(".active[location="+(parseInt(location)-1)+"]");
            tileSiblings.currentTile = currentTray.find(".active[location="+(parseInt(location))+"]");
            tileSiblings.centreRighttile = currentTray.find(".active[location="+(parseInt(location)+1)+"]");

        if(bottomTray.length)
        {
            tileSiblings.bottomLefttile = bottomTray.find(".active[location="+(parseInt(location)+parseInt(numberOfBlocksPerRow)-1)+"]");
            tileSiblings.bottomCentretile = bottomTray.find(".active[location="+(parseInt(location)+parseInt(numberOfBlocksPerRow))+"]");
            tileSiblings.bottomRighttile = bottomTray.find(".active[location="+(parseInt(location)+parseInt(numberOfBlocksPerRow+1))+"]");
        }
       /*check for mines in the sibling tiles*/
      checkForMines.call(this,tileSiblings);

    }

    var findMines = function()
    {

            /*check if te player has clicked on mine*/
            if(mineMap.indexOf(parseInt($(this).attr("location"))) === -1 )
            {
                var location = $(this).attr("location");
                var currentTray = $(this).closest(".tray");
                var topTray = currentTray.prev(".tray");
                var bottomTray = currentTray.next(".tray");
                mapSiblingTiles.call(this,location,currentTray,topTray,bottomTray,this);
            }
            else
            {
                $(this).addClass("mine");
                alert("gameover");
                init();
            }

    };
    var allMinesIdentified = function()
    {
        playerMineMap.push(parseInt($(this).attr("location")));
        if($(playerMineMap).not(mineMap).length == 0 && $(mineMap).not(playerMineMap).length == 0)
        {
            alert("You Win");
            init();
        }
    };
    var flagMine = function()
    {
        $(this).toggleClass("flag");
        allMinesIdentified.call(this);

    }
    var checkMode = function()
    {

        if($("#mode").hasClass("mine"))
        {
            findMines.call(this);
        }
        else
        {
            flagMine.call(this);
        }
    };

    var setMode = function()
    {
       $(this).toggleClass("mine flag");
    }
    /*Event handler for user's click on the tile*/
    $("#colosseum").on("click",".tile.active",checkMode);
    $("#mode").on("click",setMode);
    init();

});<|endoftext|>


<commit_before>'use strict';

const electron = require('electron');
const view = require('./menu/view');

module.exports = function menu(page) {
    const insertCSS = require('./insert-css')(page);

    function addTheme(label, file) {
        return {
            label,
            file,
            click() {
                insertCSS(file);

                page.reload();
            }
        };
    }

    const tpl = [
        view,
        {
            label: 'Themes',
            submenu: [
                addTheme('default', 'none'),
                addTheme('HNU', 'hnu.css'),
                addTheme('HNU Night mode', 'hnu-night.css'),
                addTheme('Lost sunset', 'lost-sunset.css'),
                addTheme('Haxxor', 'haxxor.css')
            ]
        },
        {
            label: 'Help',
            submenu: [
                {
                    label: 'Repository',
                    click() {
                        electron.shell.openExternal('https://github.com/bjarneo/HNU');
                    }
                }
            ]
        }
    ];

    return electron.Menu.buildFromTemplate(tpl);
};
<commit_msg>rename help -> repository to website<commit_after>'use strict';

const electron = require('electron');
const view = require('./menu/view');

module.exports = function menu(page) {
    const insertCSS = require('./insert-css')(page);

    function addTheme(label, file) {
        return {
            label,
            file,
            click() {
                insertCSS(file);

                page.reload();
            }
        };
    }

    const tpl = [
        view,
        {
            label: 'Themes',
            submenu: [
                addTheme('default', 'none'),
                addTheme('HNU', 'hnu.css'),
                addTheme('HNU Night mode', 'hnu-night.css'),
                addTheme('Lost sunset', 'lost-sunset.css'),
                addTheme('Haxxor', 'haxxor.css')
            ]
        },
        {
            label: 'Help',
            submenu: [
                {
                    label: 'Website',
                    click() {
                        electron.shell.openExternal('https://github.com/bjarneo/HNU');
                    }
                }
            ]
        }
    ];

    return electron.Menu.buildFromTemplate(tpl);
};
<|endoftext|>