<commit_before>/*
 * Wegas
 * http://wegas.albasim.ch
 *
 * Copyright (c) 2018 School of Business and Engineering Vaud, Comem
 * Licensed under the MIT License
 *
 * NB: as of August 2018, Instascan needs this patch for iOS:
 * https://github.com/centogram/instascan
 *
 * When a camera access rights issue is detected, the client game can display help instructions inside a text box
 * following this widget. That box will then appear as this widget receives the additional class "error". Sample CSS:
 *     .wegas-qrcode-scanner.error ~ .qrcode-help-box {
 *         display: block;
 *     }
 *
 */

/* global Instascan */

YUI.add('wegas-qrcode-scanner', function(Y) {
    "use strict";

    var QrCodeScanner,
        CONTENTBOX = "contentBox";

    /**
     *  The QR-code scanner class.
     */
    QrCodeScanner = Y.Base.create("wegas-qrcode-scanner", Y.Widget, [Y.Wegas.Widget, Y.WidgetChild, Y.Wegas.Editable], {
        // *** Lifecycle Methods *** //
        initializer: function() {
            this.handlers = {};
            this.cameras = {};
            this.mirror = this.get("mirror");
            this.autostart = this.get("autostart");
        },
        renderUI: function() { // Create all DOM elements
            var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream,
                // Instascan bugfix from https://github.com/schmich/instascan/pull/112 :
                videoAttrs = iOS ? "muted autoplay playsinline" : "muted playsinline";
            this.get(CONTENTBOX).setContent("<button class='fa fa-qrcode initiator'>" +
                I18n.t("qrcode.startScan")+ "</button>");
            this.get(CONTENTBOX).append("
"
                + "  <button class='mirror fa fa-arrows-h'>" +
                    I18n.t("qrcode.mirror") + "</button>"
                + "

"
                + "
"
                + "    <video class='scanner' " + videoAttrs + "></video>"
                + "
"
                + "
");
        },
        syncUI: function() {
            if (this.autostart) {
                this.toggleScanner();
            }
        },
        bindUI: function() {
            this.get(CONTENTBOX).delegate("click", this.toggleScanner, ".initiator", this);
            this.get(CONTENTBOX).delegate("click", this.flip, ".mirror", this);
            this.get(CONTENTBOX).delegate("click", this.changeCamera, ".cameras .camera", this);
        },
        changeCamera: function(e) {
            this.startScanner(e.target.getData("cameraId"));
        },
        startScanner: function(cameraId) {
            if (this.scanner && this.currentCameraId !== cameraId) {
                this.scanner.start(this.cameras[cameraId]);
                this.currentCameraId = cameraId;
                var cb = this.get(CONTENTBOX);
                cb.one(".initiator .fa-button-label").setContent(I18n.t("qrcode.cancelScan"));
                cb.all(".camera").addClass("inactive");
                var me = cb.one('.camera[data-cameraId = "' + cameraId + '"]');
                me && me.removeClass("inactive");
            }
        },
        stopScanner: function() {
            if (this.scanner) {
                this.scanner.stop();
            }
            this.currentCameraId = null;
            var cb = this.get(CONTENTBOX);
            cb.one(".initiator .fa-button-label").setContent(I18n.t("qrcode.startScan"));
        },
        flip: function() {
            this.mirror = !this.mirror;
            if (this.scanner) {
                this.scanner.stop();

                var scanner = new Instascan.Scanner({
                    video: this.get(CONTENTBOX).one(".scanner").getDOMNode(),
                    mirror: this.mirror,
                    scanPeriod: 5
                });

                scanner.addListener('scan', Y.bind(this.process, this));

                scanner.start(this.cameras[this.currentCameraId]);
                this.scanner = scanner;
            }
        },
        toggleScanner: function() {
            Y.log("ToggleScanner");
            var cb = this.get(CONTENTBOX),
                // Enable game-specific help box for solving access rights issues:
                pt = cb.get("parentNode");
            if (!this.scanner) {
                var scanner = new Instascan.Scanner({
                    video: cb.one(".scanner").getDOMNode(),
                    mirror: this.mirror,
                    scanPeriod: 5
                });

                scanner.addListener('scan', Y.bind(this.process, this));

                Instascan.Camera.getCameras().then(Y.bind(function(cameras) {
                    if (cameras.length > 0) {
                        var list = cb.one(".cameras");
                        list.setContent();
                        for (var i in cameras) {
                            this.cameras[cameras[i].id] = cameras[i];
                            list.append("<button class='camera fa fa-camera' data-cameraId=" + cameras[i].id +
                                ">" +
                                cameras[i].name + "</button>");
                        }

                        pt.removeClass("error");
                        cb.addClass("scanning");
                        this.scanner = scanner;
                        this.startScanner(cameras[0].id);
                    } else {
                        this.showMessage("error", I18n.t("qrcode.noCamera"));
                        cb.removeClass("scanning");
                        pt.addClass("error");
                    }
                }, this)).catch(Y.bind(function(e) {
                    this.showMessage("error", I18n.t("qrcode.accessRights") + "
(" + e + ")
");
                    cb.removeClass("scanning");
                    pt.addClass("error");
                }, this));

            } else {
                //cb.one(".the_scanner") && cb.one(".the_scanner").remove();
                this.stopScanner();
                this.scanner = null;
                cb.removeClass("error");
                cb.removeClass("scanning");
            }
        },

        toggleScanner_qrScanner: function() {
            var cb = this.get(CONTENTBOX);
            if (!this.scanner) {
                var scanner = new QrScanner(cb.one(".scanner").getDOMNode(), Y.bind(this.process, this));
                this.scanner = scanner;
                this.scanner.start();
                cb.toggleClass("scanning", true);
            } else {
                cb.one("video").remove();
                this.scanner.stop();
                this.scanner = null;
                cb.toggleClass("scanning", false);
            }
        },

        process: function(qrCodeValue) {
            var o = JSON.parse(qrCodeValue);
            if (o && o.type) {
                var type = o.type;
                var payload = o.payload;
                switch (type) {
                    case "runJs":
                        this.showOverlay();
                        Y.Wegas.Facade.Variable.script.remoteEval(
                            {
                                "@class": "Script",
                                content: payload
                            },
                            {
                                on: {
                                    success: Y.bind(this.hideOverlay, this),
                                    failure:
                                        // The QR-code seems to be encoded properly for Wegas, but did generate an error:
                                        Y.bind(function(e) {
                                            this.hideOverlay();
                                            // Hide any low-level error panel:
                                            var panel = Y.one(".wegas-panel"),
                                                ok = panel && panel.one(".yui3-button");
                                            if (ok) {
                                                YUI().use('node-event-simulate', function(Y) {
                                                    ok.simulate("click");
                                                });
                                            }
                                            this.showMessage("error", I18n.t("qrcode.notUnderstood"));
                                            Y.log("*** " + I18n.t("qrcode.notUnderstood"));
                                            Y.log(" Decoded QR-code: " + qrCodeValue);
                                        }, this)
                                }
                            }
                        );
                        break;
                    case "selectChoice":
                        /* payload={
                         choiceName : "choiceName"
                         }
                         */
                        var choice = Y.Wegas.Facade.Variable.cache.find("name", payload.choiceName);
                        Y.Wegas.Facade.Variable.sendRequest({
                            request: "/QuestionDescriptor/SelectChoice/" + choice.get('id')
                                + "/Player/" + Y.Wegas.Facade.Game.get('currentPlayerId')
                                + "/StartTime/0",
                            cfg: {
                                method: "GET" // initially: POST
                            }
                        });
                        break;
                    case "cancelChoice":
                        var replies = Y.Wegas.Facade.Variable.cache.find("name", payload.choiceName).getInstance().get("replies");
                        if (replies && replies.length) {
                            // TODO reply = first
                            Y.Wegas.Facade.Variable.sendRequest({
                                request: "/QuestionDescriptor/CancelReply/" + replies[0].get('id')
                                    + "/Player/" + Wegas.Facade.Game.get('currentPlayerId'),
                                cfg: {
                                    method: "GET"
                                }
                            });
                        }
                        break;
                    case "selectValidateChoice":
                        var choice = Y.Wegas.Facade.Variable.cache.find("name", payload.choiceName);
                        Y.Wegas.Facade.Variable.sendRequest({
                            request: "/QuestionDescriptor/SelectAndValidateChoice/"
                                + choice.get('id') + "/Player/"
                                + Y.Wegas.Facade.Game.get('currentPlayerId'),
                            cfg: {
                                method: "POST"
                            }
                        });
                        break;
                    case "validateQuestion":
                        break;
                    case "openPage":
                        /*
                         payload = {
                         pageId: 123,
                         pageDisplayId :  || 'maindisplayarea'
                         }
                         */
                        break;
                }

                this.toggleScanner();
            } else {
                // The QR-code was apparently not encoded for Wegas :
                this.showMessage("error", I18n.t("qrcode.notUnderstood"));
                Y.log("*** " + I18n.t("qrcode.notUnderstood"));
                Y.log(" Decoded QR-code: " + qrCodeValue);
            }
        },
        destructor: function() {
            for (var k in this.handlers) {
                this.handlers[k].detach();
            }
        }
    }, {
        generateRunScript: function(node, content) {
            return new QRCode(node, {
                text: JSON.stringify({
                    type: "runJs",
                    payload: content.get ? content.get("content") : content.content
                })
            });
        },
        updateRunScript: function(qrCode, content) {
            qrCode.clear();
            qrCode.makeCode(JSON.stringify({
                type: "runJs",
                payload: content.get ? content.get("content") : content.content
            }));
        },
        generateSelectAndValidateChoice: function(node, choice) {
            return new QRCode(node, {
                text: JSON.stringify({
                    type: "selectValidateChoice",
                    payload: choice.get("name")
                })
            });
        },
        updateSelectAndValidateChoice: function(qrCode, choice) {
            qrCode.clear();
            qrCode.makeCode(JSON.stringify({
                type: "selectValidateChoice",
                payload: choice.get("name")
            }));
        },
        ATTRS: {
            mirror: {
                type: "boolean",
                value: false,
                view: {
                    label: "Mirror"
                }
            },
            autostart: {
                type: "boolean",
                value: false,
                view: {
                    label: "Autostart"
                }
            }
        }
    });

    Y.Wegas.QrCodeScanner = QrCodeScanner;

});
<commit_msg>qrcode scanner<commit_after>/*
 * Wegas
 * http://wegas.albasim.ch
 *
 * Copyright (c) 2018 School of Business and Engineering Vaud, Comem
 * Licensed under the MIT License
 *
 * NB: as of August 2018, Instascan needs this patch for iOS:
 * https://github.com/centogram/instascan
 *
 * When a camera access rights issue is detected, the client game can display help instructions inside a text box
 * following this widget. That box will then appear as this widget receives the additional class "error". Sample CSS:
 *     .wegas-qrcode-scanner.error ~ .qrcode-help-box {
 *         display: block;
 *     }
 *
 */

/* global Instascan */

YUI.add('wegas-qrcode-scanner', function(Y) {
    "use strict";

    var QrCodeScanner,
        CONTENTBOX = "contentBox";

    /**
     *  The QR-code scanner class.
     */
    QrCodeScanner = Y.Base.create("wegas-qrcode-scanner", Y.Widget, [Y.Wegas.Widget, Y.WidgetChild, Y.Wegas.Editable], {
        // *** Lifecycle Methods *** //
        initializer: function() {
            this.handlers = {};
            this.cameras = {};
            this.mirror = this.get("mirror");
            this.autostart = this.get("autostart");
        },
        renderUI: function() { // Create all DOM elements
            var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream,
                // Instascan bugfix from https://github.com/schmich/instascan/pull/112 :
                videoAttrs = iOS ? "muted autoplay playsinline" : "muted playsinline";
            this.get(CONTENTBOX).setContent("<button class='fa fa-qrcode initiator'>" +
                I18n.t("qrcode.startScan") + "</button>");
            this.get(CONTENTBOX).append("
"
                + "  <button class='mirror fa fa-arrows-h'>" +
                I18n.t("qrcode.mirror") + "</button>"
                + "

"
                + "
"
                + "    <video class='scanner' " + videoAttrs + "></video>"
                + "
"
                + "
");
        },
        syncUI: function() {
            if (this.autostart) {
                this.toggleScanner();
            }
        },
        bindUI: function() {
            this.get(CONTENTBOX).delegate("click", this.toggleScanner, ".initiator", this);
            this.get(CONTENTBOX).delegate("click", this.flip, ".mirror", this);
            this.get(CONTENTBOX).delegate("click", this.changeCamera, ".cameras .camera", this);
        },
        changeCamera: function(e) {
            this.startScanner(e.target.getData("cameraId"));
        },
        startScanner: function(cameraId) {
            if (this.scanner && this.currentCameraId !== cameraId) {
                this.scanner.start(this.cameras[cameraId]);
                this.currentCameraId = cameraId;
                var cb = this.get(CONTENTBOX);
                cb.one(".initiator .fa-button-label").setContent(I18n.t("qrcode.cancelScan"));
                cb.all(".camera").addClass("inactive");
                var me = cb.one('.camera[data-cameraId = "' + cameraId + '"]');
                me && me.removeClass("inactive");
            }
        },
        stopScanner: function() {
            if (this.scanner) {
                this.scanner.stop();
            }
            this.currentCameraId = null;
            var cb = this.get(CONTENTBOX);
            cb.one(".initiator .fa-button-label").setContent(I18n.t("qrcode.startScan"));
        },
        flip: function() {
            this.mirror = !this.mirror;
            if (this.scanner) {
                this.scanner.stop();

                var scanner = new Instascan.Scanner({
                    video: this.get(CONTENTBOX).one(".scanner").getDOMNode(),
                    mirror: this.mirror,
                    scanPeriod: 5
                });

                scanner.addListener('scan', Y.bind(this.process, this));

                scanner.start(this.cameras[this.currentCameraId]);
                this.scanner = scanner;
            }
        },
        toggleScanner: function() {
            Y.log("ToggleScanner");
            var cb = this.get(CONTENTBOX),
                bb = this.get("boundingBox"),
                // Enable game-specific help box for solving access rights issues:
                pt = cb.get("parentNode");
            if (!this.scanner) {
                var scanner = new Instascan.Scanner({
                    video: cb.one(".scanner").getDOMNode(),
                    mirror: this.mirror,
                    scanPeriod: 5
                });

                scanner.addListener('scan', Y.bind(this.process, this));

                Instascan.Camera.getCameras().then(Y.bind(function(cameras) {
                    if (cameras.length > 0) {
                        var list = cb.one(".cameras");
                        list.setContent();
                        for (var i in cameras) {
                            this.cameras[cameras[i].id] = cameras[i];
                            list.append("<button class='camera fa fa-camera' data-cameraId=" + cameras[i].id +
                                ">" +
                                cameras[i].name + "</button>");
                        }

                        pt.removeClass("error");
                        cb.addClass("scanning");
                        bb.addClass("bb-scanning");
                        this.scanner = scanner;
                        this.startScanner(cameras[0].id);
                    } else {
                        this.showMessage("error", I18n.t("qrcode.noCamera"));
                        cb.removeClass("scanning");
                        bb.removeClass("bb-scanning");
                        pt.addClass("error");
                    }
                }, this)).catch(Y.bind(function(e) {
                    this.showMessage("error", I18n.t("qrcode.accessRights") + "
(" + e + ")
");
                    bb.removeClass("bb-scanning");
                    cb.removeClass("scanning");
                    pt.addClass("error");
                }, this));

            } else {
                //cb.one(".the_scanner") && cb.one(".the_scanner").remove();
                this.stopScanner();
                this.scanner = null;
                cb.removeClass("error");
                bb.removeClass("bb-scanning");
                cb.removeClass("scanning");
            }
        },

        toggleScanner_qrScanner: function() {
            var cb = this.get(CONTENTBOX);
            if (!this.scanner) {
                var scanner = new QrScanner(cb.one(".scanner").getDOMNode(), Y.bind(this.process, this));
                this.scanner = scanner;
                this.scanner.start();
                cb.toggleClass("scanning", true);
            } else {
                cb.one("video").remove();
                this.scanner.stop();
                this.scanner = null;
                cb.toggleClass("scanning", false);
            }
        },

        process: function(qrCodeValue) {
            var o = JSON.parse(qrCodeValue);
            if (o && o.type) {
                var type = o.type;
                var payload = o.payload;
                switch (type) {
                    case "runJs":
                        this.showOverlay();
                        Y.Wegas.Facade.Variable.script.remoteEval(
                            {
                                "@class": "Script",
                                content: payload
                            },
                            {
                                on: {
                                    success: Y.bind(this.hideOverlay, this),
                                    failure:
                                        // The QR-code seems to be encoded properly for Wegas, but did generate an error:
                                        Y.bind(function(e) {
                                            this.hideOverlay();
                                            // Hide any low-level error panel:
                                            var panel = Y.one(".wegas-panel"),
                                                ok = panel && panel.one(".yui3-button");
                                            if (ok) {
                                                YUI().use('node-event-simulate', function(Y) {
                                                    ok.simulate("click");
                                                });
                                            }
                                            this.showMessage("error", I18n.t("qrcode.notUnderstood"));
                                            Y.log("*** " + I18n.t("qrcode.notUnderstood"));
                                            Y.log(" Decoded QR-code: " + qrCodeValue);
                                        }, this)
                                }
                            }
                        );
                        break;
                    case "selectChoice":
                        /* payload={
                         choiceName : "choiceName"
                         }
                         */
                        var choice = Y.Wegas.Facade.Variable.cache.find("name", payload.choiceName);
                        Y.Wegas.Facade.Variable.sendRequest({
                            request: "/QuestionDescriptor/SelectChoice/" + choice.get('id')
                                + "/Player/" + Y.Wegas.Facade.Game.get('currentPlayerId')
                                + "/StartTime/0",
                            cfg: {
                                method: "GET" // initially: POST
                            }
                        });
                        break;
                    case "cancelChoice":
                        var replies = Y.Wegas.Facade.Variable.cache.find("name", payload.choiceName).getInstance().get("replies");
                        if (replies && replies.length) {
                            // TODO reply = first
                            Y.Wegas.Facade.Variable.sendRequest({
                                request: "/QuestionDescriptor/CancelReply/" + replies[0].get('id')
                                    + "/Player/" + Wegas.Facade.Game.get('currentPlayerId'),
                                cfg: {
                                    method: "GET"
                                }
                            });
                        }
                        break;
                    case "selectValidateChoice":
                        var choice = Y.Wegas.Facade.Variable.cache.find("name", payload.choiceName);
                        Y.Wegas.Facade.Variable.sendRequest({
                            request: "/QuestionDescriptor/SelectAndValidateChoice/"
                                + choice.get('id') + "/Player/"
                                + Y.Wegas.Facade.Game.get('currentPlayerId'),
                            cfg: {
                                method: "POST"
                            }
                        });
                        break;
                    case "validateQuestion":
                        break;
                    case "openPage":
                        /*
                         payload = {
                         pageId: 123,
                         pageDisplayId :  || 'maindisplayarea'
                         }
                         */
                        break;
                }

                this.toggleScanner();
            } else {
                // The QR-code was apparently not encoded for Wegas :
                this.showMessage("error", I18n.t("qrcode.notUnderstood"));
                Y.log("*** " + I18n.t("qrcode.notUnderstood"));
                Y.log(" Decoded QR-code: " + qrCodeValue);
            }
        },
        destructor: function() {
            for (var k in this.handlers) {
                this.handlers[k].detach();
            }
        }
    }, {
        generateRunScript: function(node, content) {
            return new QRCode(node, {
                text: JSON.stringify({
                    type: "runJs",
                    payload: content.get ? content.get("content") : content.content
                })
            });
        },
        updateRunScript: function(qrCode, content) {
            qrCode.clear();
            qrCode.makeCode(JSON.stringify({
                type: "runJs",
                payload: content.get ? content.get("content") : content.content
            }));
        },
        generateSelectAndValidateChoice: function(node, choice) {
            return new QRCode(node, {
                text: JSON.stringify({
                    type: "selectValidateChoice",
                    payload: choice.get("name")
                })
            });
        },
        updateSelectAndValidateChoice: function(qrCode, choice) {
            qrCode.clear();
            qrCode.makeCode(JSON.stringify({
                type: "selectValidateChoice",
                payload: choice.get("name")
            }));
        },
        ATTRS: {
            mirror: {
                type: "boolean",
                value: false,
                view: {
                    label: "Mirror"
                }
            },
            autostart: {
                type: "boolean",
                value: false,
                view: {
                    label: "Autostart"
                }
            }
        }
    });

    Y.Wegas.QrCodeScanner = QrCodeScanner;

});
<|endoftext|>


<commit_before>var SETDEX_SM = {
	"Absol": {
		"ORAS RU All-Out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Adamant","ability":"Super Luck","item":"Life Orb","moves":["Knock Off","Sucker Punch","Superpower","Play Rough"]},
		"ORAS RU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Adamant","ability":"Super Luck","item":"Life Orb","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU All-out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Knock Off","Sucker Punch","Pursuit","Superpower"]},
	},
	"Absol-Mega": {
		"UU Showdown Usage": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Magic Bounce","item":"Absolite","moves":["Knock Off","Sucker Punch","Swords Dance","Superpower"]},
		"ORAS UU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU All-out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Knock Off","Sucker Punch","Pursuit","Superpower"]},
	},
	"Charizard-Mega-X": {
		"Offensive": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Tough Claws","item":"Charizardite X","moves":["Dragon Dance","Outrage","Flare Blitz","Earthquake"]},
		"Defensive": {"level":100,"evs":{"sp":8,"hp":248,"def":252},"nature":"Bold","ability":"Tough Claws","item":"Charizardite X","moves":["Outrage","Flare Blitz","Will-O-Wisp","Counter"]},
	},
	"Charizard-Mega-Y": {
		"Offensive": {"level":100,"evs":{"sd":4,"sa":252,"sp":252},"nature":"Timid","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Dragon Pulse"]},
		"Def": {"level":100,"evs":{"sp":8,"sp":252,"def":252},"nature":"Modest","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Dragon Pulse"]},
	},
	"Kyurem-Black": {
		"Choice Scarf": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Naive","ability":"Teravolt","item":"Choice Scarf","moves":["Outrage", "Fusion Bolt", "Iron Head", "Ice Beam"]},
		"Choice Band": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Naive","ability":"Teravolt","item":"Choice Band","moves":["Outrage", "Fusion Bolt", "Iron Head", "Ice Beam"]},
		"Fast Icium Z": {"level":100,"evs":{"at":252,"sp":252,"sd":4},"nature":"Jolly","ability":"Teravolt","item":"Icium Z","moves":["Outrage", "Fusion Bolt", "Iron Head", "Freeze Shock"]},
		"Bulky Icium Z": {"level":100,"evs":{"at":252,"hp":248,"spe":8},"nature":"Adamant","ability":"Teravolt","item":"Icium Z","moves":["Outrage", "Fusion Bolt", "Iron Head", "Freeze Shock"]},
	},
	"Gyarados-Mega": {
		"Standard": {"level":100,"evs":{"hp":88,"at":252,"sp":88,"def":80},"nature":"Adamant","ability":"Mold Breaker","item":"Gyaradosite","moves":["Waterfall","Crunch","Outrage","Earthquake"]},
		"Bulky": {"level":100,"evs":{"hp":104,"at":196,"sd":8,"sp":100,"def":100},"nature":"Adamant","ability":"Mold Breaker","item":"Gyaradosite","moves":["Waterfall","Crunch","Outrage","Earthquake"]},
	},
	"Magearna": {
		"Choice Specs": {"level":100,"evs":{"def":4,"sa":252,"hp":252},"nature":"Modest","ability":"Soul-Heart","item":"Choice Specs","moves":["Fleur Cannon","Aura Sphere","Ice Beam","Energy Ball"]},
	},
	"Porygon-Z": {
		"Standard Scarf": {"level":100,"evs":{"def":4,"sa":252,"sp":252},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"Bulky Scarf": {"level":100,"evs":{"def":240,"sa":172,"sp":96},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"Choice Specs": {"level":100,"evs":{"sa":252,"hp":252,"def":4},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"Breakneck Blitz": {"level":100,"evs":{"def":4,"sa":252,"sp":252},"nature":"Timid","ability":"Adaptibility","item":"Normalium Z","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
	},
};
<commit_msg>Update setdex_sm.js<commit_after>var SETDEX_SM = {
	"Absol": {
		"ORAS RU All-Out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Adamant","ability":"Super Luck","item":"Life Orb","moves":["Knock Off","Sucker Punch","Superpower","Play Rough"]},
		"ORAS RU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Adamant","ability":"Super Luck","item":"Life Orb","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU All-out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Knock Off","Sucker Punch","Pursuit","Superpower"]},
	},
	"Absol-Mega": {
		"UU Showdown Usage": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Magic Bounce","item":"Absolite","moves":["Knock Off","Sucker Punch","Swords Dance","Superpower"]},
		"ORAS UU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU All-out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Knock Off","Sucker Punch","Pursuit","Superpower"]},
	},
	"Charizard-Mega-X": {
		"OU Offensive": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Tough Claws","item":"Charizardite X","moves":["Dragon Dance","Outrage","Flare Blitz","Earthquake"]},
		"OU Defensive": {"level":100,"evs":{"sp":8,"hp":248,"def":252},"nature":"Bold","ability":"Tough Claws","item":"Charizardite X","moves":["Outrage","Flare Blitz","Will-O-Wisp","Counter"]},
	},
	"Charizard-Mega-Y": {
		"OU Offensive": {"level":100,"evs":{"sd":4,"sa":252,"sp":252},"nature":"Timid","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Dragon Pulse"]},
		"OU Def": {"level":100,"evs":{"sp":8,"sp":252,"def":252},"nature":"Modest","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Dragon Pulse"]},
	},
	"Kyurem-Black": {
		"OU Choice Scarf": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Naive","ability":"Teravolt","item":"Choice Scarf","moves":["Outrage", "Fusion Bolt", "Iron Head", "Ice Beam"]},
		"OU Choice Band": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Naive","ability":"Teravolt","item":"Choice Band","moves":["Outrage", "Fusion Bolt", "Iron Head", "Ice Beam"]},
		"OU Fast Icium Z": {"level":100,"evs":{"at":252,"sp":252,"sd":4},"nature":"Jolly","ability":"Teravolt","item":"Icium Z","moves":["Outrage", "Fusion Bolt", "Iron Head", "Freeze Shock"]},
		"OU Bulky Icium Z": {"level":100,"evs":{"at":252,"hp":248,"spe":8},"nature":"Adamant","ability":"Teravolt","item":"Icium Z","moves":["Outrage", "Fusion Bolt", "Iron Head", "Freeze Shock"]},
	},
	"Gyarados-Mega": {
		"OU Standard": {"level":100,"evs":{"hp":88,"at":252,"sp":88,"def":80},"nature":"Adamant","ability":"Mold Breaker","item":"Gyaradosite","moves":["Waterfall","Crunch","Outrage","Earthquake"]},
		"OU Bulky": {"level":100,"evs":{"hp":104,"at":196,"sd":8,"sp":100,"def":100},"nature":"Adamant","ability":"Mold Breaker","item":"Gyaradosite","moves":["Waterfall","Crunch","Outrage","Earthquake"]},
	},
	"Magearna": {
		"OU Choice Specs": {"level":100,"evs":{"def":4,"sa":252,"hp":252},"nature":"Modest","ability":"Soul-Heart","item":"Choice Specs","moves":["Fleur Cannon","Aura Sphere","Ice Beam","Energy Ball"]},
	},
	"Porygon-Z": {
		"OU Standard Scarf": {"level":100,"evs":{"def":4,"sa":252,"sp":252},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Bulky Scarf": {"level":100,"evs":{"def":240,"sa":172,"sp":96},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Choice Specs": {"level":100,"evs":{"sa":252,"hp":252,"def":4},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Breakneck Blitz": {"level":100,"evs":{"def":4,"sa":252,"sp":252},"nature":"Timid","ability":"Adaptibility","item":"Normalium Z","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
	},
};
<|endoftext|>


<commit_before>var SETDEX_SM = {
	"Absol": {
		"ORAS RU All-Out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Adamant","ability":"Super Luck","item":"Life Orb","moves":["Knock Off","Sucker Punch","Superpower","Play Rough"]},
		"ORAS RU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Adamant","ability":"Super Luck","item":"Life Orb","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU All-out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Knock Off","Sucker Punch","Pursuit","Superpower"]},
	},
	"Absol-Mega": {
		"UU Showdown Usage": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Magic Bounce","item":"Absolite","moves":["Knock Off","Sucker Punch","Swords Dance","Superpower"]},
		"ORAS UU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU All-out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Knock Off","Sucker Punch","Pursuit","Superpower"]},
	},
	"Charizard-Mega-X": {
		"OU Offensive": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Tough Claws","item":"Charizardite X","moves":["Dragon Dance","Outrage","Flare Blitz","Earthquake"]},
		"OU Defensive": {"level":100,"evs":{"sp":8,"hp":248,"def":252},"nature":"Bold","ability":"Tough Claws","item":"Charizardite X","moves":["Outrage","Flare Blitz","Will-O-Wisp","Counter"]},
	},
	"Charizard-Mega-Y": {
		"OU Offensive": {"level":100,"evs":{"sd":4,"sa":252,"sp":252},"nature":"Timid","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Dragon Pulse"]},
		"1v1 Offensivemon": {"level":100,"evs":{"sd":4,"sa":252,"sp":252},"nature":"Timid","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Ancient Power"]},
		"OU Def": {"level":100,"evs":{"sp":8,"sp":252,"def":252},"nature":"Modest","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Dragon Pulse"]},
	},
	"Kyurem-Black": {
		"OU Choice Scarf": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Naive","ability":"Teravolt","item":"Choice Scarf","moves":["Outrage", "Fusion Bolt", "Iron Head", "Ice Beam"]},
		"OU Choice Band": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Naive","ability":"Teravolt","item":"Choice Band","moves":["Outrage", "Fusion Bolt", "Iron Head", "Ice Beam"]},
		"OU Fast Icium Z": {"level":100,"evs":{"at":252,"sp":252,"sd":4},"nature":"Jolly","ability":"Teravolt","item":"Icium Z","moves":["Outrage", "Fusion Bolt", "Iron Head", "Freeze Shock"]},
		"OU Bulky Icium Z": {"level":100,"evs":{"at":252,"hp":248,"spe":8},"nature":"Adamant","ability":"Teravolt","item":"Icium Z","moves":["Outrage", "Fusion Bolt", "Iron Head", "Freeze Shock"]},
	},
	"Gyarados-Mega": {
		"OU Standard": {"level":100,"evs":{"hp":88,"at":252,"sp":88,"def":80},"nature":"Adamant","ability":"Mold Breaker","item":"Gyaradosite","moves":["Waterfall","Crunch","Outrage","Earthquake"]},
		"OU Bulky": {"level":100,"evs":{"hp":104,"at":196,"sd":8,"sp":100,"def":100},"nature":"Adamant","ability":"Mold Breaker","item":"Gyaradosite","moves":["Waterfall","Crunch","Outrage","Earthquake"]},
	},
	"Magearna": {
		"OU Choice Specs": {"level":100,"evs":{"def":4,"sa":252,"hp":252},"nature":"Modest","ability":"Soul-Heart","item":"Choice Specs","moves":["Fleur Cannon","Aura Sphere","Ice Beam","Energy Ball"]},
	},
	"Porygon-Z": {
		"OU Standard Scarf": {"level":100,"evs":{"def":4,"sa":252,"sp":252},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Bulky Scarf": {"level":100,"evs":{"def":240,"sa":172,"sp":96},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Choice Specs": {"level":100,"evs":{"sa":252,"hp":252,"def":4},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Breakneck Blitz": {"level":100,"evs":{"def":4,"sa":252,"sp":252},"nature":"Timid","ability":"Adaptibility","item":"Normalium Z","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
	},
};
<commit_msg>Update setdex_sm.js<commit_after>var SETDEX_SM = {
	"Absol": {
		"ORAS RU All-Out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Adamant","ability":"Super Luck","item":"Life Orb","moves":["Knock Off","Sucker Punch","Superpower","Play Rough"]},
		"ORAS RU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Adamant","ability":"Super Luck","item":"Life Orb","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU All-out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Knock Off","Sucker Punch","Pursuit","Superpower"]},
	},
	"Absol-Mega": {
		"UU Showdown Usage": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Magic Bounce","item":"Absolite","moves":["Knock Off","Sucker Punch","Swords Dance","Superpower"]},
		"ORAS UU Swords Dance": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Swords Dance","Knock Off","Sucker Punch","Superpower"]},
		"ORAS UU All-out Attacker": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Justified","item":"Absolite","moves":["Knock Off","Sucker Punch","Pursuit","Superpower"]},
	},
	"Charizard-Mega-X": {
		"OU Offensive": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Jolly","ability":"Tough Claws","item":"Charizardite X","moves":["Dragon Dance","Outrage","Flare Blitz","Earthquake"]},
		"OU Defensive": {"level":100,"evs":{"sp":8,"hp":248,"def":252},"nature":"Bold","ability":"Tough Claws","item":"Charizardite X","moves":["Outrage","Flare Blitz","Will-O-Wisp","Counter"]},
	},
	"Charizard-Mega-Y": {
		"OU Offensive": {"level":100,"evs":{"sd":4,"sa":252,"sp":252},"nature":"Timid","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Dragon Pulse"]},
		"1v1 Offensivemon": {"level":100,"evs":{"sd":4,"sa":252,"sp":252},"nature":"Timid","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Ancient Power"]},
		"OU Def": {"level":100,"evs":{"sp":8,"sp":252,"def":252},"nature":"Modest","ability":"Drought","item":"Charizardite Y","moves":["Air Slash","Blast Burn","Solar Beam","Dragon Pulse"]},
	},
	"Kyurem-Black": {
		"OU Choice Scarf": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Naive","ability":"Teravolt","item":"Choice Scarf","moves":["Outrage", "Fusion Bolt", "Iron Head", "Ice Beam"]},
		"OU Choice Band": {"level":100,"evs":{"sd":4,"at":252,"sp":252},"nature":"Naive","ability":"Teravolt","item":"Choice Band","moves":["Outrage", "Fusion Bolt", "Iron Head", "Ice Beam"]},
		"OU Fast Icium Z": {"level":100,"evs":{"at":252,"sp":252,"sd":4},"nature":"Jolly","ability":"Teravolt","item":"Icium Z","moves":["Outrage", "Fusion Bolt", "Iron Head", "Freeze Shock"]},
		"OU Bulky Icium Z": {"level":100,"evs":{"at":252,"hp":248,"spe":8},"nature":"Adamant","ability":"Teravolt","item":"Icium Z","moves":["Outrage", "Fusion Bolt", "Iron Head", "Freeze Shock"]},
	},
	"Gyarados-Mega": {
		"OU Standard": {"level":100,"evs":{"hp":88,"at":252,"sp":88,"def":80},"nature":"Adamant","ability":"Mold Breaker","item":"Gyaradosite","moves":["Waterfall","Crunch","Outrage","Earthquake"]},
		"OU Bulky": {"level":100,"evs":{"hp":104,"at":196,"sd":8,"sp":100,"def":100},"nature":"Adamant","ability":"Mold Breaker","item":"Gyaradosite","moves":["Waterfall","Crunch","Outrage","Earthquake"]},
	},
	"Magearna": {
		"OU Choice Specs": {"level":100,"evs":{"def":4,"sa":252,"hp":252},"nature":"Modest","ability":"Soul-Heart","item":"Choice Specs","moves":["Fleur Cannon","Aura Sphere","Ice Beam","Energy Ball"]},
	},
	"Porygon-Z": {
		"OU Standard Scarf": {"level":100,"evs":{"def":4,"sa":252,"sp":252},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Bulky Scarf": {"level":100,"evs":{"def":240,"sa":172,"sp":96},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Choice Specs": {"level":100,"evs":{"sa":252,"hp":252,"def":4},"nature":"Timid","ability":"Adaptibility","item":"Choice Scarf","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
		"OU Breakneck Blitz": {"level":100,"evs":{"def":4,"sa":252,"sp":252},"nature":"Timid","ability":"Adaptibility","item":"Normalium Z","moves":["Hyper Beam", "Uproar", "Shadow Ball", "Ice Beam"]},
	},
};
<|endoftext|>


<commit_before>var uninstall = require('../src/uninstall'),
    install = require('../src/install'),
    android = require('../src/platforms/android'),
    ios     = require('../src/platforms/ios'),
    blackberry = require('../src/platforms/blackberry'),
    xml_helpers = require('../src/util/xml-helpers'),
    config_changes = require('../src/util/config-changes'),
    plugman = require('../plugman'),
    fs      = require('fs'),
    et      = require('elementtree'),
    os      = require('osenv'),
    path    = require('path'),
    shell   = require('shelljs'),
    temp    = path.join(os.tmpdir(), 'plugman'),
    childbrowser = path.join(__dirname, 'plugins', 'ChildBrowser'),
    dummyplugin = path.join(__dirname, 'plugins', 'DummyPlugin'),
    variableplugin = path.join(__dirname, 'plugins', 'VariablePlugin'),
    faultyplugin = path.join(__dirname, 'plugins', 'FaultyPlugin'),
    android_one_project = path.join(__dirname, 'projects', 'android_one', '*'),
    blackberry_project = path.join(__dirname, 'projects', 'blackberry', '*'),
    ios_project = path.join(__dirname, 'projects', 'ios-config-xml', '*'),
    plugins_dir = path.join(temp, 'cordova', 'plugins');

describe('uninstall', function() {
    var copied_plugin_path = path.join(temp,'ChildBrowser');

    beforeEach(function() {
        shell.mkdir('-p', temp);
        shell.mkdir('-p', plugins_dir);
        shell.cp('-rf', android_one_project, temp);
        shell.cp('-rf', dummyplugin, plugins_dir);
    });
    afterEach(function() {
        shell.rm('-rf', temp);
    });

    describe('success', function() {
        var android_uninstaller;
        beforeEach(function() {
            install('android', temp, 'DummyPlugin', plugins_dir, {});
            android_uninstaller = spyOn(android, 'uninstall');
        });
        it('should generate and pass uninstall transaction log to appropriate platform handler\'s uninstall', function() {
            uninstall('android', temp, 'DummyPlugin', plugins_dir, {});
            var transactions = android_uninstaller.mostRecentCall.args[0];

            expect(transactions.length).toEqual(6);
            expect(transactions[0].tag).toBe('source-file');
        });
        it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method', function() {
            uninstall('android', temp, 'DummyPlugin', plugins_dir, {});
            var spy = spyOn(config_changes, 'add_uninstalled_plugin_to_prepare_queue');
            android_uninstaller.mostRecentCall.args[4](null); // fake out handler uninstall callback
            expect(spy).toHaveBeenCalledWith(plugins_dir, 'DummyPlugin', 'android');
        });
    });

    describe('failure', function() {
        it('should throw if platform is unrecognized', function() {
            expect(function() {
                uninstall('atari', temp, 'SomePlugin', plugins_dir, {});
            }).toThrow('atari not supported.');
        });
        it('should throw if the plugin was not found', function() {
            expect(function() {
                uninstall('android', temp, 'SomePlugin', plugins_dir, {});
            }).toThrow('Plugin "SomePlugin" not found. Already uninstalled?');
        });
        it('should handle a failed uninstall by passing completed transactions into appropriate handler\'s install method', function() {
            shell.cp('-rf', faultyplugin, plugins_dir);
            install('android', temp, 'DummyPlugin', plugins_dir, {});
            var s = spyOn(android, 'install');
            // destroy android manifest /manifest/application so pruneXML fails
            var manifest_path = path.join(temp, 'AndroidManifest.xml');
            var manifest = xml_helpers.parseElementtreeSync(manifest_path);
            var app_el = manifest.find('application');
            manifest.getroot().remove(0, app_el);
            var output = manifest.write({indent:4});
            fs.writeFileSync(manifest_path, output);

            uninstall('android', temp, 'DummyPlugin', plugins_dir, {});
            var executed_txs = s.mostRecentCall.args[0];
            expect(executed_txs.length).toEqual(1);
            // It only ended up "uninstalling" one source file, so install reversion should pass in that source file to re-install
            expect(executed_txs[0].tag).toEqual('source-file');
        });
    });
});
<commit_msg>fixing some tests in uninstall following refactor<commit_after>var uninstall = require('../src/uninstall'),
    install = require('../src/install'),
    android = require('../src/platforms/android'),
    ios     = require('../src/platforms/ios'),
    blackberry = require('../src/platforms/blackberry'),
    xml_helpers = require('../src/util/xml-helpers'),
    config_changes = require('../src/util/config-changes'),
    plugman = require('../plugman'),
    fs      = require('fs'),
    et      = require('elementtree'),
    os      = require('osenv'),
    path    = require('path'),
    shell   = require('shelljs'),
    temp    = path.join(os.tmpdir(), 'plugman'),
    childbrowser = path.join(__dirname, 'plugins', 'ChildBrowser'),
    dummyplugin = path.join(__dirname, 'plugins', 'DummyPlugin'),
    variableplugin = path.join(__dirname, 'plugins', 'VariablePlugin'),
    faultyplugin = path.join(__dirname, 'plugins', 'FaultyPlugin'),
    android_one_project = path.join(__dirname, 'projects', 'android_one', '*'),
    blackberry_project = path.join(__dirname, 'projects', 'blackberry', '*'),
    ios_project = path.join(__dirname, 'projects', 'ios-config-xml', '*'),
    plugins_dir = path.join(temp, 'cordova', 'plugins');

describe('uninstall', function() {
    var copied_plugin_path = path.join(temp,'ChildBrowser');

    beforeEach(function() {
        shell.mkdir('-p', temp);
        shell.mkdir('-p', plugins_dir);
        shell.cp('-rf', android_one_project, temp);
        shell.cp('-rf', dummyplugin, plugins_dir);
    });
    afterEach(function() {
        shell.rm('-rf', temp);
    });

    describe('success', function() {
        var android_uninstaller;
        beforeEach(function() {
            install('android', temp, 'DummyPlugin', plugins_dir, {});
            android_uninstaller = spyOn(android, 'uninstall');
        });
        it('should generate and pass uninstall transaction log to appropriate platform handler\'s uninstall', function() {
            uninstall('android', temp, 'DummyPlugin', plugins_dir, {});
            var transactions = android_uninstaller.mostRecentCall.args[0];

            expect(transactions.length).toEqual(3);
            expect(transactions[0].tag).toBe('source-file');
        });
        it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method', function() {
            uninstall('android', temp, 'DummyPlugin', plugins_dir, {});
            var spy = spyOn(config_changes, 'add_uninstalled_plugin_to_prepare_queue');
            android_uninstaller.mostRecentCall.args[4](null); // fake out handler uninstall callback
            expect(spy).toHaveBeenCalledWith(plugins_dir, 'DummyPlugin', 'android');
        });
    });

    describe('failure', function() {
        it('should throw if platform is unrecognized', function() {
            expect(function() {
                uninstall('atari', temp, 'SomePlugin', plugins_dir, {});
            }).toThrow('atari not supported.');
        });
        it('should throw if the plugin was not found', function() {
            expect(function() {
                uninstall('android', temp, 'SomePlugin', plugins_dir, {});
            }).toThrow('Plugin "SomePlugin" not found. Already uninstalled?');
        });
        it('should handle a failed uninstall by passing completed transactions into appropriate handler\'s install method', function() {
            shell.cp('-rf', faultyplugin, plugins_dir);
            install('android', temp, 'DummyPlugin', plugins_dir, {});

            // make uninstall fail by removing a js asset
            shell.rm(path.join(temp, 'assets', 'www', 'dummyplugin.js'));
            var s = spyOn(android, 'install');
            uninstall('android', temp, 'DummyPlugin', plugins_dir, {});
            var executed_txs = s.mostRecentCall.args[0];
            expect(executed_txs.length).toEqual(1);
            // It only ended up "uninstalling" one source file, so install reversion should pass in that source file to re-install
            expect(executed_txs[0].tag).toEqual('source-file');
        });
    });
});
<|endoftext|>


<commit_before>/* jshint node: true */

module.exports = function (environment) {
  var ENV = {
    modulePrefix: 'pix-live',
    environment: environment,
    rootURL: '/',
    locationType: 'auto',
    EmberENV: {
      // XXX because of a deprecation notice in the console
      EXTEND_PROTOTYPES: {
        Date: false
      },
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      },
      useDelay: true,

    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
      API_HOST: '/'
    },

    googleFonts: [
      'Lato:300,300i,400,400i,600,600i,700,700i', // main font
      'Open+Sans:300,300i,400,400i,600,600i,700,700i' // used for ex. on buttons
    ],

    // Set or update content security policies
    contentSecurityPolicy: {
      'font-src': "'self' fonts.gstatic.com",
      'style-src': "'self' fonts.googleapis.com"
    }
  };

  if (environment === 'development') {
    // LOG
    ENV.APP.LOG_RESOLVER = false;
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_TRANSITIONS = false;
    ENV.APP.LOG_TRANSITIONS_INTERNAL = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    // Redefined in custom initializer 'initializers/configure-pix-api-host.js'
    ENV.APP.API_HOST= 'http://localhost:3000'
  }

  if (environment === 'test') {
    ENV.EmberENV.useDelay = false;

    // Testem prefers this...
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
    ENV.googleFonts = [];
    ENV.APP.API_HOST= 'http://localhost:3000';
  }

  if (environment === 'integration') {
    ENV.metricsAdapters = [
      {
        name: 'Piwik',
        environments: ['integration'],
        config: {
          piwikUrl: '//stats.data.gouv.fr',
          siteId: 30
        }
      },
      {
        name: 'GoogleAnalytics',
        environments: ['integration'],
        config: {
          id: 'UA-87429411-1'
        }
      }
    ];
  }

  if (environment === 'staging') {
    ENV.metricsAdapters = [
      {
        name: 'Piwik',
        environments: ['staging'],
        config: {
          piwikUrl: '//stats.data.gouv.fr',
          siteId: 31
        }
      },
      {
        name: 'GoogleAnalytics',
        environments: ['staging'],
        config: {
          id: 'UA-87429411-1'
        }
      }
    ];
  }

  if (environment === 'production') {
    ENV.metricsAdapters = [
      {
        name: 'Piwik',
        environments: ['production'],
        config: {
          piwikUrl: '//stats.data.gouv.fr',
          siteId: 29
        }
      },
      {
        name: 'GoogleAnalytics',
        environments: ['production'],
        config: {
          id: 'UA-87412969-1'
        }
      }
    ];
  }

  return ENV;
};
<commit_msg>[#160] [FEATURE] Suppression du tracking Google Analytics<commit_after>/* jshint node: true */

module.exports = function (environment) {
  var ENV = {
    modulePrefix: 'pix-live',
    environment: environment,
    rootURL: '/',
    locationType: 'auto',
    EmberENV: {
      // XXX because of a deprecation notice in the console
      EXTEND_PROTOTYPES: {
        Date: false
      },
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      },
      useDelay: true,

    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
      API_HOST: '/'
    },

    googleFonts: [
      'Lato:300,300i,400,400i,600,600i,700,700i', // main font
      'Open+Sans:300,300i,400,400i,600,600i,700,700i' // used for ex. on buttons
    ],

    // Set or update content security policies
    contentSecurityPolicy: {
      'font-src': "'self' fonts.gstatic.com",
      'style-src': "'self' fonts.googleapis.com"
    }
  };

  if (environment === 'development') {
    // LOG
    ENV.APP.LOG_RESOLVER = false;
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_TRANSITIONS = false;
    ENV.APP.LOG_TRANSITIONS_INTERNAL = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    // Redefined in custom initializer 'initializers/configure-pix-api-host.js'
    ENV.APP.API_HOST= 'http://localhost:3000'
  }

  if (environment === 'test') {
    ENV.EmberENV.useDelay = false;

    // Testem prefers this...
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
    ENV.googleFonts = [];
    ENV.APP.API_HOST= 'http://localhost:3000';
  }

  if (environment === 'integration') {
    ENV.metricsAdapters = [
      {
        name: 'Piwik',
        environments: ['integration'],
        config: {
          piwikUrl: '//stats.data.gouv.fr',
          siteId: 30
        }
      }
    ];
  }

  if (environment === 'staging') {
    ENV.metricsAdapters = [
      {
        name: 'Piwik',
        environments: ['staging'],
        config: {
          piwikUrl: '//stats.data.gouv.fr',
          siteId: 31
        }
      }
    ];
  }

  if (environment === 'production') {
    ENV.metricsAdapters = [
      {
        name: 'Piwik',
        environments: ['production'],
        config: {
          piwikUrl: '//stats.data.gouv.fr',
          siteId: 29
        }
      }
    ];
  }

  return ENV;
};
<|endoftext|>


<commit_before>var card_width = 300;
var card_height = 186;
var half_card_width = card_width / 2;
var half_card_height = card_height / 2;

var next_outgoing_i = 0; /* the index of the next node that's outgoing */
var next_incoming_i = 0;

/* Which card is currently displayed in the middle of the screen? */
var current_card = null;

/* Height of rendered graph */
var graph_height = null;
var min_graph_height = 808;

// scrolling
var top_row_offset = 0;
var bottom_row_offset = 0;

var nodes = [];
var cards = [];
var relations = []; // relations are between nodes
var links = []; // links are between cards

var nodes = [];
var relations = [];

function indexOfNode(node_id) {
    for (i = 0; i < nodes.length; i++) {
        if (nodes[i].id === node_id) {
            return i;
        }
    }
    return -1; // not found
}

function indexOfRelation(relation_id) {
    for (i = 0; i < relations.length; i++) {
        if (relations[i].id === relation_id) {
            return i;
        }
    }
    return -1; // not found
}

function set_incoming_and_outgoing(relation) {
    if (get_other_id(relation) === null) {
        relation.from.outgoing.push(relation.to);
        relation.to.incoming.push(relation.from);
    }
}

function set_relation_id(relation, node) {
    if (relation.from === node.id) {
        relation.from = node;
    } else if (relation.to === node.id) {
        relation.to = node;
    } else {
        console.log("Uh oh, node " + node.id + " not found for relation " + relation.id);
    }

    set_incoming_and_outgoing(relation);
}

function get_other_id(relation) {
    // call this after calling "set_relation_id"
    if (typeof relation.from === 'number') {
        return relation.from;
    } else if (typeof relation.to === 'number') {
        return relation.to;
    } else {
        return null;
    }
}

function ajax_get_node(node_id, callback) {
    // if node already exists, DON'T evenn call this function!
    // mock ajax function for now
    $.ajax({
        url: "mock_ajax/" + node_id + ".json",
        type: "GET",
        dataType: "json",
    }).done(function (data) {
        data.incoming = [];
        data.outgoing = [];
        nodes.push(data);
        if (typeof callback !== 'undefined') {
            callback(data);
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        console.log("Failed to get node " + node_id + ": " + errorThrown);
    });
}

function ajax_get_relation_nodes_function(new_relation, existing_node) {
    // http://stackoverflow.com/a/750506/257583
    return function () {
        if (indexOfRelation(new_relation.id) === -1) { // it's a new relation
            set_relation_id(new_relation, existing_node);
            var missing_id = get_other_id(new_relation);
            var missing_index = indexOfNode(missing_id);
            if (missing_index === -1) { // node is currently missing
                ajax_get_node(missing_id, function (new_node) {
                    set_relation_id(new_relation, new_node);
                    relations.push(new_relation);
                    draw_graph();
                })
            } else { // node already exists, just use it
                set_relation_id(new_relation, nodes[missing_index]);
                relations.push(new_relation);
            }
        }
    }
}

function ajax_get_relations_of(node, callback) {
    // get relations and make sure that nodes for relations get fetched as well
    // mock ajax function for now
    $.ajax({
        url: "mock_ajax/arg_" + node.id + "_relations.json",
        type: "GET",
        dataType: "json",
    }).done(function (data) {
        ajax_relation_nodes_functions = []
        for (var i = 0; i < data.length; i++) {
            ajax_relation_nodes_functions.push(ajax_get_relation_nodes_function(data[i], node));
        }
        for (var i = 0; i < ajax_relation_nodes_functions.length; i++) {
            ajax_relation_nodes_functions[i]();
        }
        if (typeof callback !== 'undefined') {
            callback(data);
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        console.log("Failed to get relations of node " + node.id + ": " + errorThrown);
    });
}

function ajax_get_card(node) {
    ajax_get_relations_of(node, function (relations) {
        draw_graph();
    });
}

function is_outgoing(node) {
    return current_card.outgoing.indexOf(node) != -1;
}

function is_incoming(node) {
    return current_card.incoming.indexOf(node) != -1;
}

function node_visible(node) {
    return (node == current_card) || is_outgoing(node) || is_incoming(node);
}

function link_visible(link) {
    // both ends of a link must be visible for a link to be visible
    return node_visible(link.from) && node_visible(link.to);
}

function x_pos(node) {
    if (node == current_card) {
        node.i = 0; // doesn't matter for current_card
        return (window.innerWidth / 2) - half_card_width;
    } else if (is_outgoing(node)) {
        if (node.i == null) {
            node.i = next_outgoing_i;
            next_outgoing_i++;
        }
        return top_row_offset + (node.i * (card_width + 10) + 10);
    } else if (is_incoming(node)) {
        if (node.i == null) {
            node.i = next_incoming_i;
            next_incoming_i++;
        }
        return bottom_row_offset + (node.i * (card_width + 10) + 10);
    } else {
        if (node.previously_current) {
            return window.innerWidth + 10;
        } else if (node.previously_outgoing || node.previously_incoming) {
            return (window.innerWidth / 2) - half_card_width;
        }
    }
}

function y_pos(node) {
    if (node == current_card) {
        return (graph_height / 2) - half_card_height;
    } else if (is_outgoing(node)) {
        return 10;
    } else if (is_incoming(node)) {
        return graph_height - 10 - card_height;
    } else {
        if (node.previously_current) {
            return (graph_height / 2) - half_card_height;
        } else if (node.previously_outgoing) {
            return -10 - card_height;
        } else if (node.previously_incoming) {
            return graph_height + 10;
        } else {
            console.log(node);
        }
    }
}

function min_top_row_offset() {
    return Math.min(0, window.innerWidth - (20 + next_outgoing_i * (card_width + 11)));
}

function min_bottom_row_offset() {
    return Math.min(0, window.innerWidth - (20 + next_incoming_i * (card_width + 11)));
}

function max_top_row_offset() {
    return Math.min(0, window.innerWidth - (10 + next_outgoing_i * (card_width + 10)));
}

function max_bottom_row_offset() {
    return Math.min(0, window.innerWidth - (20 + next_incoming_i * (card_width + 10)));
}

var drag = d3.behavior.drag()
            .on("drag", function () {
                console.log("woo");
                if (d3.event.y <= (card_height + 20)) {
                    top_row_offset += d3.event.dx;
                    draw_graph(0);

                    if ((top_row_offset < 0) && (top_row_offset < min_top_row_offset())) {
                        top_row_offset = min_top_row_offset();
                        draw_graph();
                    }
                } else if (d3.event.y >= (graph_height - card_height - 20)) {
                    bottom_row_offset += d3.event.dx;
                    draw_graph(0);

                    if ((bottom_row_offset < 0) && (bottom_row_offset < min_bottom_row_offset())) {
                        bottom_row_offset = min_bottom_row_offset();
                        draw_graph();
                    }
                }
            })

function pos2str(pos) {
    return pos[0] + "," + pos[1] + " ";
}

function compute_link_bezier_curve(link) {
    var from = link.from;
    var to = link.to;
    var start_pos = [x_pos(from, from.i) + half_card_width, y_pos(from, from.i)];
    var end_pos = [x_pos(to, to.i) + half_card_width,
                    /* marker-widht is 3, stroke-width is 5 */
                   y_pos(to, to.i) + card_height + (5 * 3)];
    var height = end_pos[1] - start_pos[1];
    var control1 = [start_pos[0], start_pos[1] + (height / 2)];
    var control2 = [end_pos[0], end_pos[1] - (height / 2)];
    return "M" + pos2str(start_pos) + "C" + pos2str(control1)
            + pos2str(control2) + pos2str(end_pos);
}

function reset_globals() {
    for (var i=0; i < nodes.length; i++) {
        node = nodes[i];
        node.i = null;
    }
    next_outgoing_i = 0;
    next_incoming_i = 0;
}

function make_cards() {
    var svg = d3.select("svg#graph");
    cards = svg.selectAll("g").data(nodes);
    new_cards = cards.enter().append("g").classed("argument", true);
    new_cards.append("rect").attr("width", card_width).attr("height", card_height)
                .style("opacity", 0).call(drag);
    var switch_objects = new_cards.append("switch").call(drag);
    switch_objects.append("foreignObject").classed("foreign-object", true)
            .attr("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Extensibility")
            .attr("width", card_width).attr("height", card_height)
            .append("xhtml:div").classed("summary", true).append("p")
            .classed("summary", true).text(function (d) {
                return d.summary;
            }).attr("xmlns", "http://www.w3.org/1999/xhtml");
    switch_objects.append("text").attr("x", 100).attr("y", 100)
        .text("Sorry, your browser is not currently supported.");
    new_cards.on("click", function (d) {
        if (d3.event.defaultPrevented) return;

        top_row_offset = 0;
        bottom_row_offset = 0;

        current_card = d;
        ajax_get_card(d);
        draw_graph();
    })
}

function make_links() {
    var svg = d3.select("svg#graph");
    links = svg.selectAll("path").data(relations);
    links.enter().append("path")
        .attr("class", function(d) {
            return d.type;
        }).attr("marker-end", function(d) {
            return "url(#arrow-" + d.type + ")";
        }).style("opacity", 0);
}

function draw_graph(transition_time) {
    transition_time = typeof transition_time === 'undefined' ? 500 : transition_time;

    reset_globals();
    make_cards();
    make_links();

    var svg = d3.select("svg#graph");
    d3.selectAll("g rect").transition().duration(transition_time)
        .attr("x", x_pos).attr("y", y_pos).style("opacity", 1);
    // http://stackoverflow.com/a/11743721/257583
    // also, doesn't matter if the text is opaque or not since it's the
    // same color as the background
    d3.selectAll(".foreign-object").transition().duration(transition_time)
        .attr("x", x_pos).attr("y", y_pos);
    cards.each(function (d) {
        if (current_card == d) {
            d.previously_current = true;
            d.previously_outgoing = false;
            d.previously_incoming = false;
        } else if (is_outgoing(d)) {
            d.previously_current = false;
            d.previously_outgoing = true;
            d.previously_incoming = false;
        } else if (is_incoming(d)) {
            d.previously_current = false;
            d.previously_outgoing = false;
            d.previously_incoming = true;
        } // else shouldn't happen
    });
    links.transition().duration(transition_time).style("opacity", function (d) {
        // if one end of the link is currently displayed, then the other is too
        if (link_visible(d)) {
            return 1;
        } else {
            return 0;
        }
    }).attr("d", compute_link_bezier_curve);
}

window.onload = function () {
    if ($("#graph").height() < min_graph_height) {
        alert("Whoops, looks like some things won't be displaying correctly. Please tell us about this.");
    }
    graph_height = $("#graph").height();
    ajax_get_node(1, function (data) {
        current_card = data;
        draw_graph();

        ajax_get_relations_of(nodes[0], function (data) {
            draw_graph();
        })
    })

    draw_graph();
}<commit_msg>Refactored min_top_row_offset to be more intuitive<commit_after>var card_width = 300;
var card_height = 186;
var half_card_width = card_width / 2;
var half_card_height = card_height / 2;

var next_outgoing_i = 0; /* the index of the next node that's outgoing */
var next_incoming_i = 0;

/* Which card is currently displayed in the middle of the screen? */
var current_card = null;

/* Height of rendered graph */
var graph_height = null;
var min_graph_height = 808;

// scrolling
var top_row_offset = 0;
var bottom_row_offset = 0;

var nodes = [];
var cards = [];
var relations = []; // relations are between nodes
var links = []; // links are between cards

var nodes = [];
var relations = [];

function indexOfNode(node_id) {
    for (i = 0; i < nodes.length; i++) {
        if (nodes[i].id === node_id) {
            return i;
        }
    }
    return -1; // not found
}

function indexOfRelation(relation_id) {
    for (i = 0; i < relations.length; i++) {
        if (relations[i].id === relation_id) {
            return i;
        }
    }
    return -1; // not found
}

function set_incoming_and_outgoing(relation) {
    if (get_other_id(relation) === null) {
        relation.from.outgoing.push(relation.to);
        relation.to.incoming.push(relation.from);
    }
}

function set_relation_id(relation, node) {
    if (relation.from === node.id) {
        relation.from = node;
    } else if (relation.to === node.id) {
        relation.to = node;
    } else {
        console.log("Uh oh, node " + node.id + " not found for relation " + relation.id);
    }

    set_incoming_and_outgoing(relation);
}

function get_other_id(relation) {
    // call this after calling "set_relation_id"
    if (typeof relation.from === 'number') {
        return relation.from;
    } else if (typeof relation.to === 'number') {
        return relation.to;
    } else {
        return null;
    }
}

function ajax_get_node(node_id, callback) {
    // if node already exists, DON'T evenn call this function!
    // mock ajax function for now
    $.ajax({
        url: "mock_ajax/" + node_id + ".json",
        type: "GET",
        dataType: "json",
    }).done(function (data) {
        data.incoming = [];
        data.outgoing = [];
        nodes.push(data);
        if (typeof callback !== 'undefined') {
            callback(data);
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        console.log("Failed to get node " + node_id + ": " + errorThrown);
    });
}

function ajax_get_relation_nodes_function(new_relation, existing_node) {
    // http://stackoverflow.com/a/750506/257583
    return function () {
        if (indexOfRelation(new_relation.id) === -1) { // it's a new relation
            set_relation_id(new_relation, existing_node);
            var missing_id = get_other_id(new_relation);
            var missing_index = indexOfNode(missing_id);
            if (missing_index === -1) { // node is currently missing
                ajax_get_node(missing_id, function (new_node) {
                    set_relation_id(new_relation, new_node);
                    relations.push(new_relation);
                    draw_graph();
                })
            } else { // node already exists, just use it
                set_relation_id(new_relation, nodes[missing_index]);
                relations.push(new_relation);
            }
        }
    }
}

function ajax_get_relations_of(node, callback) {
    // get relations and make sure that nodes for relations get fetched as well
    // mock ajax function for now
    $.ajax({
        url: "mock_ajax/arg_" + node.id + "_relations.json",
        type: "GET",
        dataType: "json",
    }).done(function (data) {
        ajax_relation_nodes_functions = []
        for (var i = 0; i < data.length; i++) {
            ajax_relation_nodes_functions.push(ajax_get_relation_nodes_function(data[i], node));
        }
        for (var i = 0; i < ajax_relation_nodes_functions.length; i++) {
            ajax_relation_nodes_functions[i]();
        }
        if (typeof callback !== 'undefined') {
            callback(data);
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        console.log("Failed to get relations of node " + node.id + ": " + errorThrown);
    });
}

function ajax_get_card(node) {
    ajax_get_relations_of(node, function (relations) {
        draw_graph();
    });
}

function is_outgoing(node) {
    return current_card.outgoing.indexOf(node) != -1;
}

function is_incoming(node) {
    return current_card.incoming.indexOf(node) != -1;
}

function node_visible(node) {
    return (node == current_card) || is_outgoing(node) || is_incoming(node);
}

function link_visible(link) {
    // both ends of a link must be visible for a link to be visible
    return node_visible(link.from) && node_visible(link.to);
}

function x_pos(node) {
    if (node == current_card) {
        node.i = 0; // doesn't matter for current_card
        return (window.innerWidth / 2) - half_card_width;
    } else if (is_outgoing(node)) {
        if (node.i == null) {
            node.i = next_outgoing_i;
            next_outgoing_i++;
        }
        return top_row_offset + (node.i * (card_width + 10) + 10);
    } else if (is_incoming(node)) {
        if (node.i == null) {
            node.i = next_incoming_i;
            next_incoming_i++;
        }
        return bottom_row_offset + (node.i * (card_width + 10) + 10);
    } else {
        if (node.previously_current) {
            return window.innerWidth + 10;
        } else if (node.previously_outgoing || node.previously_incoming) {
            return (window.innerWidth / 2) - half_card_width;
        }
    }
}

function y_pos(node) {
    if (node == current_card) {
        return (graph_height / 2) - half_card_height;
    } else if (is_outgoing(node)) {
        return 10;
    } else if (is_incoming(node)) {
        return graph_height - 10 - card_height;
    } else {
        if (node.previously_current) {
            return (graph_height / 2) - half_card_height;
        } else if (node.previously_outgoing) {
            return -10 - card_height;
        } else if (node.previously_incoming) {
            return graph_height + 10;
        } else {
            console.log(node);
        }
    }
}

function row_width(num_cards) {
    return 10 + (num_cards * (card_width + 10));
}

function min_top_row_offset() {
    if (row_width(next_outgoing_i) > window.innerWidth) { // must allow scrolling
        return window.innerWidth - row_width(next_outgoing_i);
    } else {
        return 0;
    }
}

function min_bottom_row_offset() {
    return Math.min(0, window.innerWidth - (20 + next_incoming_i * (card_width + 11)));
}

function max_top_row_offset() {
    return Math.min(0, window.innerWidth - (10 + next_outgoing_i * (card_width + 10)));
}

function max_bottom_row_offset() {
    return Math.min(0, window.innerWidth - (20 + next_incoming_i * (card_width + 10)));
}

var drag = d3.behavior.drag()
            .on("drag", function () {
                if (d3.event.y <= (card_height + 20)) {
                    top_row_offset += d3.event.dx;
                    draw_graph(0);

                    if ((top_row_offset < 0) && (top_row_offset < min_top_row_offset())) {
                        top_row_offset = min_top_row_offset();
                        draw_graph(0);
                    }
                } else if (d3.event.y >= (graph_height - card_height - 20)) {
                    bottom_row_offset += d3.event.dx;
                    draw_graph(0);

                    if ((bottom_row_offset < 0) && (bottom_row_offset < min_bottom_row_offset())) {
                        bottom_row_offset = min_bottom_row_offset();
                        draw_graph();
                    }
                }
            })

function pos2str(pos) {
    return pos[0] + "," + pos[1] + " ";
}

function compute_link_bezier_curve(link) {
    var from = link.from;
    var to = link.to;
    var start_pos = [x_pos(from, from.i) + half_card_width, y_pos(from, from.i)];
    var end_pos = [x_pos(to, to.i) + half_card_width,
                    /* marker-widht is 3, stroke-width is 5 */
                   y_pos(to, to.i) + card_height + (5 * 3)];
    var height = end_pos[1] - start_pos[1];
    var control1 = [start_pos[0], start_pos[1] + (height / 2)];
    var control2 = [end_pos[0], end_pos[1] - (height / 2)];
    return "M" + pos2str(start_pos) + "C" + pos2str(control1)
            + pos2str(control2) + pos2str(end_pos);
}

function reset_globals() {
    for (var i=0; i < nodes.length; i++) {
        node = nodes[i];
        node.i = null;
    }
    next_outgoing_i = 0;
    next_incoming_i = 0;
}

function make_cards() {
    var svg = d3.select("svg#graph");
    cards = svg.selectAll("g").data(nodes);
    new_cards = cards.enter().append("g").classed("argument", true);
    new_cards.append("rect").attr("width", card_width).attr("height", card_height)
                .style("opacity", 0).call(drag);
    var switch_objects = new_cards.append("switch").call(drag);
    switch_objects.append("foreignObject").classed("foreign-object", true)
            .attr("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Extensibility")
            .attr("width", card_width).attr("height", card_height)
            .append("xhtml:div").classed("summary", true).append("p")
            .classed("summary", true).text(function (d) {
                return d.summary;
            }).attr("xmlns", "http://www.w3.org/1999/xhtml");
    switch_objects.append("text").attr("x", 100).attr("y", 100)
        .text("Sorry, your browser is not currently supported.");
    new_cards.on("click", function (d) {
        if (d3.event.defaultPrevented) return;

        top_row_offset = 0;
        bottom_row_offset = 0;

        current_card = d;
        ajax_get_card(d);
        draw_graph();
    })
}

function make_links() {
    var svg = d3.select("svg#graph");
    links = svg.selectAll("path").data(relations);
    links.enter().append("path")
        .attr("class", function(d) {
            return d.type;
        }).attr("marker-end", function(d) {
            return "url(#arrow-" + d.type + ")";
        }).style("opacity", 0);
}

function draw_graph(transition_time) {
    transition_time = typeof transition_time === 'undefined' ? 500 : transition_time;

    reset_globals();
    make_cards();
    make_links();

    var svg = d3.select("svg#graph");
    d3.selectAll("g rect").transition().duration(transition_time)
        .attr("x", x_pos).attr("y", y_pos).style("opacity", 1);
    // http://stackoverflow.com/a/11743721/257583
    // also, doesn't matter if the text is opaque or not since it's the
    // same color as the background
    d3.selectAll(".foreign-object").transition().duration(transition_time)
        .attr("x", x_pos).attr("y", y_pos);
    cards.each(function (d) {
        if (current_card == d) {
            d.previously_current = true;
            d.previously_outgoing = false;
            d.previously_incoming = false;
        } else if (is_outgoing(d)) {
            d.previously_current = false;
            d.previously_outgoing = true;
            d.previously_incoming = false;
        } else if (is_incoming(d)) {
            d.previously_current = false;
            d.previously_outgoing = false;
            d.previously_incoming = true;
        } // else shouldn't happen
    });
    links.transition().duration(transition_time).style("opacity", function (d) {
        // if one end of the link is currently displayed, then the other is too
        if (link_visible(d)) {
            return 1;
        } else {
            return 0;
        }
    }).attr("d", compute_link_bezier_curve);
}

window.onload = function () {
    if ($("#graph").height() < min_graph_height) {
        alert("Whoops, looks like some things won't be displaying correctly. Please tell us about this.");
    }
    graph_height = $("#graph").height();
    ajax_get_node(1, function (data) {
        current_card = data;
        draw_graph();

        ajax_get_relations_of(nodes[0], function (data) {
            draw_graph();
        })
    })

    draw_graph();
}<|endoftext|>


<commit_before>var todostore = require('./todoStore');
var TodoActions = require('./TodoActions');
import BLLayerLoader from './../common/BLLayerLoader.js';

var bridge = BLLayerLoader.getBLBridge();

todostore.on('change', function () {
	bridge.post("/stores/TodoStore/updateState", todostore.getState());
});

bridge.on("/stores/TodoStore/getInitialState", function (payload, sendBack) {
	sendBack(todostore.getState());
});
//TODO , support * Syntax
//bridge.on("/actions/TodoActions/*", function (payload, sendBack, path) {
//	var x = path.split("/");
//	x.splice(0, 1);
//	var method = x[2];
//	TodoActions[method].call(TodoActions, payload);
//});

bridge.on("/actions/TodoActions/addTodo", function (payload, sendBack, path) {
	TodoActions.addTodo(payload);
});

bridge.on("/actions/TodoActions/markComplete", function (payload, sendBack, path) {
	TodoActions.markComplete(payload);
});

bridge.on("/actions/TodoActions/remove", function (payload, sendBack, path) {
	TodoActions.remove(payload);
});

bridge.on("/actions/TodoActions/removeAllCompleted", function (payload, sendBack, path) {
	TodoActions.removeAllCompleted();
});

bridge.on("/actions/TodoActions/edit", function (payload, sendBack, path) {
	TodoActions.edit(payload.id, payload.text);
});

bridge.on("/actions/TodoActions/markUnComplete", function (payload, sendBack, path) {
	TodoActions.markUnComplete(payload);
});

bridge.on("/actions/TodoActions/markAllUnComplete", function (payload, sendBack, path) {
	TodoActions.markAllUnComplete();
});

bridge.on("/actions/TodoActions/markAllComplete", function (payload, sendBack, path) {
	TodoActions.markAllComplete();
});<commit_msg>added info<commit_after>var todostore = require('./todoStore');
var TodoActions = require('./TodoActions');
import BLLayerLoader from './../common/BLLayerLoader.js';

var bridge = BLLayerLoader.getBLBridge();

todostore.on('change', function () {
	bridge.post("/stores/TodoStore/updateState", todostore.getState());
});

bridge.on("/stores/TodoStore/getInitialState", function (payload, sendBack) {
	sendBack(todostore.getState());
});

//TODO , support : Syntax
//bridge.on("/actions/TodoActions/:method", function (payload, sendBack, path) {
//	var method = path.params.method
//  path.url = "/actions/TodoActions/addTodo"
//  path.matchedUrl = "/actions/TodoActions/:method"
//	TodoActions[method].call(TodoActions, payload);
//});

bridge.on("/actions/TodoActions/addTodo", function (payload, sendBack, path) {
	TodoActions.addTodo(payload);
});

bridge.on("/actions/TodoActions/markComplete", function (payload, sendBack, path) {
	TodoActions.markComplete(payload);
});

bridge.on("/actions/TodoActions/remove", function (payload, sendBack, path) {
	TodoActions.remove(payload);
});

bridge.on("/actions/TodoActions/removeAllCompleted", function (payload, sendBack, path) {
	TodoActions.removeAllCompleted();
});

bridge.on("/actions/TodoActions/edit", function (payload, sendBack, path) {
	TodoActions.edit(payload.id, payload.text);
});

bridge.on("/actions/TodoActions/markUnComplete", function (payload, sendBack, path) {
	TodoActions.markUnComplete(payload);
});

bridge.on("/actions/TodoActions/markAllUnComplete", function (payload, sendBack, path) {
	TodoActions.markAllUnComplete();
});

bridge.on("/actions/TodoActions/markAllComplete", function (payload, sendBack, path) {
	TodoActions.markAllComplete();
});<|endoftext|>


<commit_before>/*
 * Copyright 2012 The Toolkitchen Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */(function(e){var t=function(e,t){return Array.prototype.slice.call(e,t||0)};Function.prototype.bind||(Function.prototype.bind=function(e){var n=this,r=t(arguments,1);return function(){var i=t(arguments,0);return n.apply(e,r.concat(i))}}),e=e||{},e.clone=function(e,n){var r=t(arguments,1);for(var i=0,s;s=r[i];i++)if(s)for(var o in s)e[o]=s[o];return e},window.__PointerEventShim__=e})(window.__PointerEventShim__),function(e){var t={pointers:[],addPointer:function(e,t){var n={id:e,event:t};return this.pointers.push(n),n},removePointer:function(e){var t=this.getPointerIndex(e);if(t>-1)return this.pointers.splice(t,1)},getPointerById:function(e){return this.pointers[this.getPointerIndex(e)]},getPointerIndex:function(e){for(var t=0,n=this.pointers.length,r;t<n&&(r=this.pointers[t]);t++)if(r.id===e)return t;return-1},getPointerList:function(){return this.pointers}};e.pointermap=t}(window.__PointerEventShim__),function(e){var t=e.clone,n=e.pointermap,r=n.getPointerList.bind(n),i={hooks:[],events:{},eventSources:{},registerSource:function(e,t,n){n.forEach(function(e){t[e]&&(this.events[e]=t[e].bind(t))},this),this.listen(n),this.eventSources[e]=t},registerHook:function(e,t,n){this.hooks.push({scope:t,events:n,name:e})},down:function(e){this.fireEvent(e,"pointerdown")},move:function(e){this.fireEvent(e,"pointermove")},up:function(e){this.fireEvent(e,"pointerup")},tap:function(e){this.disableTap||this.fireEvent(e,"pointertap")},enter:function(e){this.fireEvent(e,"pointerenter")},leave:function(e){this.fireEvent(e,"pointerleave")},eventHandler:function(e){var t=e.type,n=this.events&&this.events[t];n&&n(e)},listen:function(e){e.forEach(function(e){this.addEvent(e,this.boundHandler)},this)},unlisten:function(e){e.forEach(function(e){this.removeEvent(e,this.boundHandler)},this)},addEvent:function(e,t,n){document.addEventListener(e,t,n)},removeEvent:function(e,t,n){document.removeEventListener(e,t,n)},makeEvent:function(e,t){var n;typeof e.buttons!="undefined"?n=e.buttons?e.button:-1:n=e.which?e.button:-1;var i=document.createEvent("MouseEvent");return i.initMouseEvent(t,e.bubbles,e.cancelable,e.view,e.detail,e.screenX,e.screenY,e.clientX,e.clientY,e.ctrlKey,e.altKey,e.shiftKey,e.metaKey,n,e.relatedTarget),i.srcEvent=e.srcEvent||e,i.pointerId=e.pointerId||-1,i.getPointerList=r,i},fireEvent:function(e,t){var n=this.makeEvent(e,t);return this.dispatchEvent(n)},cloneEvent:function(e){return t({},e)},findTarget:function(e){return e.target},dispatchEvent:function(e){var t=e.type;for(var n=0,r,i;r=this.hooks[n];n++)if(r.events.indexOf(t)>-1){i=r.scope[t];if(i&&i.call(r.scope,e)===!0)return}return this.findTarget(e.srcEvent).dispatchEvent(e)}};e.dispatcher=i,i.boundHandler=i.eventHandler.bind(i)}(window.__PointerEventShim__),function(e){var t=e.dispatcher,n=e.pointermap,r=function(e,t){var n=e;while(n){if(n===t)return!0;n=n.parentNode}},i={events:["click","touchstart","touchmove","touchend"],splitEvents:function(e){var n=Array.prototype.map.call(e.changedTouches,function(e){var n=t.cloneEvent(e);return n.pointerId=e.identifier,n.target=this.findTarget(n),n.bubbles=!0,n.cancelable=!0,n.which=1,n.button=0,n},this);return n},findTarget:function(e){return document.elementFromPoint(e.clientX,e.clientY)},click:function(e){t.tap(e)},touchstart:function(e){var t=this.splitEvents(e);t.forEach(this.downEnter,this)},downEnter:function(e){var r=n.addPointer(e.pointerId,e,null);t.down(e),r.over=e,t.enter(e)},touchmove:function(e){e.preventDefault();var t=this.splitEvents(e);t.forEach(this.moveEnterLeave,this)},moveEnterLeave:function(e){var i=e,s=n.getPointerById(i.pointerId),o=s.over;s.event=i,t.move(i),o&&o.target!==i.target&&(o.relatedTarget=i.target,i.relatedTarget=o.target,r(o.relatedTarget,o.target)||t.leave(o),r(i.relatedTarget,i.target)||t.enter(i)),s.over=i},touchend:function(e){var t=this.splitEvents(e);t.forEach(this.upLeave,this)},upLeave:function(e){t.up(e),t.leave(e),n.removePointer(e.pointerId)}},s={POINTER_ID:-1,buttons:0,events:["click","mousedown","mousemove","mouseup","mouseover","mouseout"],click:function(e){t.tap(e)},mousedown:function(e){if(e.button==2)return;this.buttons==0&&(n.addPointer(this.POINTER_ID,e),t.down(e)),this.buttons++},mousemove:function(e){var r=n.getPointerById(this.POINTER_ID);r&&(r.event=e),t.move(e)},mouseup:function(e){this.buttons--,this.buttons==0&&(t.up(e),n.removePointer(this.POINTER_ID))},mouseover:function(e){if(!r(e.relatedTarget,e.target)){var n=t.cloneEvent(e);n.bubbles=!1,t.enter(n)}},mouseout:function(e){if(!r(e.relatedTarget,e.target)){var n=t.cloneEvent(e);n.bubbles=!1,t.leave(n)}}};"ontouchstart"in window?t.registerSource("touch",i,i.events):t.registerSource("mouse",s,s.events)}(window.__PointerEventShim__);<commit_msg>update build for refactoring<commit_after>/*
 * Copyright 2012 The Toolkitchen Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */(function(e){var t=function(e,t){return Array.prototype.slice.call(e,t||0)};Function.prototype.bind||(Function.prototype.bind=function(e){var n=this,r=t(arguments,1);return function(){var i=t(arguments,0);return n.apply(e,r.concat(i))}}),e=e||{},e.clone=function(e,n){var r=t(arguments,1);for(var i=0,s;s=r[i];i++)if(s)for(var o in s)e[o]=s[o];return e},window.__PointerEventShim__=e})(window.__PointerEventShim__),function(e){var t={pointers:[],addPointer:function(e,t){var n={id:e,event:t};return this.pointers.push(n),n},removePointer:function(e){var t=this.getPointerIndex(e);if(t>-1)return this.pointers.splice(t,1)},getPointerById:function(e){return this.pointers[this.getPointerIndex(e)]},getPointerIndex:function(e){for(var t=0,n=this.pointers.length,r;t<n&&(r=this.pointers[t]);t++)if(r.id===e)return t;return-1},getPointerList:function(){return this.pointers}};e.pointermap=t}(window.__PointerEventShim__),function(e){var t=e.clone,n=e.pointermap,r=n.getPointerList.bind(n),i={events:[],eventMap:{},eventSources:{},registerSource:function(e,t){this.events=t.events,this.events.forEach(function(e){t[e]&&(this.eventMap[e]=t[e].bind(t))},this),this.eventSources[e]=t},registerTarget:function(e){this.listen(this.events,e)},unregisterTarget:function(e){this.unlisten(this.events,e)},down:function(e){this.fireEvent(e,"pointerdown")},move:function(e){this.fireEvent(e,"pointermove")},up:function(e){this.fireEvent(e,"pointerup")},tap:function(e){this.disableTap||this.fireEvent(e,"pointertap")},enter:function(e){this.fireEvent(e,"pointerenter")},leave:function(e){this.fireEvent(e,"pointerleave")},eventHandler:function(e){if(e.__pointerHandled__)return;var t=e.type,n=this.eventMap&&this.eventMap[t];n&&n(e),e.__pointerHandled__=!0},listen:function(e,t){e.forEach(function(e){this.addEvent(e,this.boundHandler,!1,t)},this)},unlisten:function(e){e.forEach(function(e){this.removeEvent(e,this.boundHandler,!1,inTarget)},this)},addEvent:function(e,t,n,r){var i=r||document;i.addEventListener(e,t,n)},removeEvent:function(e,t,n,r){var i=r||document;i.removeEventListener(e,t,n)},makeEvent:function(e,t){var n;typeof e.buttons!="undefined"?n=e.buttons?e.button:-1:n=e.which?e.button:-1;var i=document.createEvent("MouseEvent");return i.initMouseEvent(t,e.bubbles,e.cancelable,e.view,e.detail,e.screenX,e.screenY,e.clientX,e.clientY,e.ctrlKey,e.altKey,e.shiftKey,e.metaKey,n,e.relatedTarget),i.__srcTarget__=e.__srcTarget__||e.target,i.pointerId=e.pointerId||-1,i.getPointerList=r,i},fireEvent:function(e,t){var n=this.makeEvent(e,t);return this.dispatchEvent(n)},cloneEvent:function(e){return t({},e)},dispatchEvent:function(e){return e.__srcTarget__.dispatchEvent(e)}};e.dispatcher=i,i.boundHandler=i.eventHandler.bind(i)}(window.__PointerEventShim__),function(e){var t=e.dispatcher,n=e.pointermap,r=function(e,t){var n=e;while(n){if(n===t)return!0;n=n.parentNode}},i={events:["click","touchstart","touchmove","touchend"],splitEvents:function(e){var n=Array.prototype.map.call(e.changedTouches,function(e){var n=t.cloneEvent(e);return n.pointerId=e.identifier,n.target=this.findTarget(n),n.bubbles=!0,n.cancelable=!0,n.which=1,n.button=0,n},this);return n},findTarget:function(e){return document.elementFromPoint(e.clientX,e.clientY)},click:function(e){t.tap(e)},touchstart:function(e){var t=this.splitEvents(e);t.forEach(this.downEnter,this)},downEnter:function(e){var r=n.addPointer(e.pointerId,e,null);t.down(e),r.over=e,t.enter(e)},touchmove:function(e){e.preventDefault();var t=this.splitEvents(e);t.forEach(this.moveEnterLeave,this)},moveEnterLeave:function(e){var i=e,s=n.getPointerById(i.pointerId),o=s.over;s.event=i,t.move(i),o&&o.target!==i.target&&(o.relatedTarget=i.target,i.relatedTarget=o.target,r(o.relatedTarget,o.target)||t.leave(o),r(i.relatedTarget,i.target)||t.enter(i)),s.over=i},touchend:function(e){var t=this.splitEvents(e);t.forEach(this.upLeave,this)},upLeave:function(e){t.up(e),t.leave(e),n.removePointer(e.pointerId)}},s={POINTER_ID:-1,buttons:0,events:["click","mousedown","mousemove","mouseup","mouseover","mouseout"],click:function(e){t.tap(e)},mousedown:function(e){if(e.button==2)return;this.buttons==0&&(n.addPointer(this.POINTER_ID,e),t.down(e)),this.buttons++},mousemove:function(e){var r=n.getPointerById(this.POINTER_ID);r&&(r.event=e),t.move(e)},mouseup:function(e){this.buttons--,this.buttons==0&&(t.up(e),n.removePointer(this.POINTER_ID))},mouseover:function(e){if(!r(e.relatedTarget,e.target)){var n=t.cloneEvent(e);n.bubbles=!1,t.enter(n)}},mouseout:function(e){if(!r(e.relatedTarget,e.target)){var n=t.cloneEvent(e);n.bubbles=!1,t.leave(n)}}};"ontouchstart"in window?t.registerSource("touch",i):t.registerSource("mouse",s),t.registerTarget(document)}(window.__PointerEventShim__);<|endoftext|>