<commit_before>angular.module('symbolApp')
    .factory('symbolIdCodeService', ['config', 'pathService', function (config, pathService) {
        var symbolIdCode = {};
        var undef = {"label": "Undefined", digits: "00"};
        var SVG_PATH = config.SVG_PATH;
        var alternateAmplifiers = false;
        symbolIdCode.versionCode1 = "1";
        symbolIdCode.versionCode2 = "0";
        symbolIdCode.context = symbolData.contexts[0];
        symbolIdCode.standardIdentity = symbolData.standardIdentities[3];
        symbolIdCode.symbolSet = symbolData.symbolSets[4];
        symbolIdCode.status = symbolData.statuses[0];
        symbolIdCode.hqtfDummy = symbolData.hqtfDummies[0];
        symbolIdCode.amplifier = symbolData.amplifier[1];
        symbolIdCode.amplifierDescriptor = symbolData.amplifier[1].descriptors[5];
        symbolIdCode.entity = symbolIdCode.symbolSet.entities[1];
        symbolIdCode.entityType = symbolIdCode.entity.entityTypes[2];
        symbolIdCode.entitySubType = symbolIdCode.entityType.entitySubTypes[0];
        symbolIdCode.sectorOneModifier = null;
        symbolIdCode.sectorTwoModifier = null;
        symbolIdCode.useCivilianFrame = false;

        function computeSymbolIdentificationCode() {
            var sic = symbolIdCode;
            var version = sic.versionCode1 + sic.versionCode2;
            var context = sic.context ? sic.context.digits : "0";
            var standardIdentity = sic.standardIdentity ? sic.standardIdentity.digits : "0";
            var symbolSet = sic.symbolSet ? sic.symbolSet.digits : "00";
            var status = sic.status ? sic.status.digits : "0";
            var hqtfDummy = sic.hqtfDummy ? sic.hqtfDummy.digits : "0";
            var amplifier = sic.amplifier ? sic.amplifier.digits : "0";
            var amplifierDescriptor = sic.amplifierDescriptor ? sic.amplifierDescriptor.digits : "0";
            var entity = sic.entity ? sic.entity.digits : "00";
            var entityType = sic.entityType ? sic.entityType.digits : "00";
            var entitySubType = sic.entitySubType ? sic.entitySubType.digits : "00";
            var mod1 = sic.sectorOneModifier ? sic.sectorOneModifier.digits : "00";
            var mod2 = sic.sectorTwoModifier ? sic.sectorTwoModifier.digits : "00";

            return version + context + standardIdentity + symbolSet + status + hqtfDummy + amplifier + amplifierDescriptor
                + entity + entityType + entitySubType + mod1 + mod2;

        }

        function getEntityFn() {
            var gg = symbolIdCode.entitySubType || symbolIdCode.entityType || symbolIdCode.entity;
            return pathService.getEntityFilePath(gg, symbolIdCode.symbolSet, symbolIdCode.standardIdentity.id);
        }

        function getFrameFn() {
            var sic = symbolIdCode;
            return pathService.getFrameFilePath(sic.context.id, sic.standardIdentity.id, sic.symbolSet, sic.status, sic.useCivilianFrame);
        }

        function getStatusFn() {
            var sic = symbolIdCode;
            return pathService.getStatusFilePath(sic.standardIdentity.id, sic.symbolSet, sic.status, alternateAmplifiers);
        }

        function getHqtfdFn() {
            var sic = symbolIdCode;
            return pathService.getHqtfdFilePath(sic.standardIdentity.id, sic.symbolSet, sic.hqtfDummy);
        }

        function getAmplifierFn() {
            var sic = symbolIdCode;
            return pathService.getAmplifierFilePath(sic.standardIdentity.id, sic.amplifierDescriptor);

        }

        function getModifierOneFn() {
            var fn = "";
            var sic = symbolIdCode;
            if (sic.symbolSet && sic.sectorOneModifier && sic.sectorOneModifier.digits !== "00") {
                fn = sic.symbolSet.digits + sic.sectorOneModifier.digits;
            }
            return fn ? SVG_PATH + symbolIdCode.symbolSet.graphicFolder["modifierOnes"] + "/" + fn + "1.svg" : null;
        }

        function getModifierTwoFn() {
            var fn = "";
            var sic = symbolIdCode;
            if (sic.sectorTwoModifier) {
                fn = sic.symbolSet.digits + sic.sectorTwoModifier.digits;
            }
            if (sic.sectorTwoModifier && sic.sectorTwoModifier.digits == "00") {
                return null
            }
            return fn ? SVG_PATH + symbolIdCode.symbolSet.graphicFolder["modifierTwos"] + "/" + fn + "2.svg" : null;
        }

        function getAlternateAmplifiers() {
            return alternateAmplifiers;
        }

        function setAlternateAmplifiers(alternateAmplifiersValue) {
            alternateAmplifiers = alternateAmplifiersValue;
        }

        return {
            symbId: symbolIdCode,
            getEntityFn: getEntityFn,
            getFrameFn: getFrameFn,
            getStatusFn: getStatusFn,
            getHqtfdFn: getHqtfdFn,
            getAmplifilerFn: getAmplifierFn,
            getModiferOneFn: getModifierOneFn,
            getModiferTwoFn: getModifierTwoFn,
            getAlternateAmplifiers: getAlternateAmplifiers,
            setAlternateAmplifiers: setAlternateAmplifiers,
            setStandardIdentity: function (standardIdentity) {
                symbolIdCode.standardIdentity = standardIdentity;
            },
            setContext: function (context) {
                symbolIdCode.context = context;
            },
            setSymbolSet: function (symbolSet) {
                symbolIdCode.symbolSet = symbolSet;
            },
            setStatus: function (status) {
                symbolIdCode.status = status;
            },
            setAmplifier: function (amplifer) {
                symbolIdCode.amplifier = amplifer;
            },
            setAmplifierDescriptor: function (amplifierDescriptor) {
                symbolIdCode.amplifierDescriptor = amplifierDescriptor;

            },
            setHQTFDummy: function (hqTFDummy) {
                symbolIdCode.hqtfDummy = hqTFDummy;
            },
            setEntity: function (entity) {
                symbolIdCode.entity = entity;
            },
            setEntityType: function (entityType) {
                symbolIdCode.entityType = entityType;
            },
            setEntitySubType: function (entitySubType) {
                symbolIdCode.entitySubType = entitySubType;
            },
            setSectorOneModifier: function (sectorOneModifier) {
                symbolIdCode.sectorOneModifier = sectorOneModifier || {"label": "Undefined", "digits": "00"};
            },
            setSectorTwoModifier: function (sectorTwoModifier) {
                symbolIdCode.sectorTwoModifier = sectorTwoModifier || {"label": "Undefined", "digits": "00"};
            },
            getSymbolIdentificationCode: function () {
                return computeSymbolIdentificationCode();
            }
        };
    }])

    .controller('SymbolCtrl', ['$scope', '$log', 'symbolIdCodeService', 'disableModOneFilter',
        'disableModTwoFilter', 'limitUseToModFilterFilter',
        function ($scope, $log, symbolIdCodeService, disableModOneFilter, disableModTwoFilter, limitUseToModFilterFilter) {
            $scope.frame = symbolIdCodeService.getFrameFn;
            $scope.main = symbolIdCodeService.getEntityFn;
            $scope.amplifierFn = symbolIdCodeService.getAmplifilerFn;
            $scope.modifierOneFn = symbolIdCodeService.getModiferOneFn;
            $scope.modifierTwoFn = symbolIdCodeService.getModiferTwoFn;
            $scope.statusFn = symbolIdCodeService.getStatusFn;
            $scope.hqtfdFn = symbolIdCodeService.getHqtfdFn;
            $scope.symbolData = symbolData;
            $scope.hqtfDummy = symbolIdCodeService.symbId.hqtfDummy;
            $scope.context = symbolIdCodeService.symbId.context;
            $scope.standardIdentity = symbolIdCodeService.symbId.standardIdentity;
            $scope.currentSymbolSet = symbolIdCodeService.symbId.symbolSet;
            $scope.status = symbolIdCodeService.symbId.status;
            $scope.amplifier = symbolIdCodeService.symbId.amplifier;
            $scope.amplifierDescriptor = symbolIdCodeService.symbId.amplifierDescriptor;
            $scope.symbId = symbolIdCodeService.symbId;
            $scope.ss = symbolIdCodeService;
            $scope.entity = symbolIdCodeService.symbId.entity;
            $scope.entityType = symbolIdCodeService.symbId.entityType;
            $scope.entitySubType = symbolIdCodeService.symbId.entitySubType;
            $scope.sectorOneModifier = symbolIdCodeService.symbId.sectorOneModifier;
            $scope.alternateAmplifiers = symbolIdCodeService.getAlternateAmplifiers();
            $scope.limitUseTo = true;
            $scope.currentEntity = $scope.entitySubType || $scope.entityType || $scope.entity;
            $scope.showDebugInfo = false;

            $scope.changeContext = function (context) {
                symbolIdCodeService.setContext(context);
            };

            $scope.changeStandardIdentity = function (standardIdentity) {
                symbolIdCodeService.setStandardIdentity(standardIdentity);

            };

            $scope.changeSymbolSet = function (symbolSet) {
                symbolIdCodeService.setSymbolSet(symbolSet);
                $scope.entity = null;

                $scope.entity = symbolSet.entities[0];
                $scope.changeEntity(symbolSet.entities[0]);
                $scope.sectorOneModifier = null;
                $scope.sectorTwoModifier = null;
                symbolIdCodeService.setSectorOneModifier(null);
                symbolIdCodeService.setSectorTwoModifier(null);
                $scope.amplifier = symbolData.amplifier[0];
                $scope.changeAmplifier(symbolData.amplifier[0]);

            };

            $scope.changeStatus = function (status) {
                symbolIdCodeService.setStatus(status);
            };

            $scope.changeAlternateAmplifiers = function (alternateAmplifiers) {
                symbolIdCodeService.setAlternateAmplifiers(alternateAmplifiers);
            };

            $scope.changeHQTFDummy = function (hqTfDummy) {
                symbolIdCodeService.setHQTFDummy(hqTfDummy);
            };

            $scope.changeAmplifier = function (amplifier) {
                symbolIdCodeService.setAmplifier(amplifier);
                $scope.amplifierDescriptor = amplifier.descriptors[0];
                $scope.changeAmplifierDescriptor(amplifier.descriptors[0]);
            };

            $scope.changeAmplifierDescriptor = function (amplifierDescriptor) {
                symbolIdCodeService.setAmplifierDescriptor(amplifierDescriptor);
            };

            $scope.changeEntity = function (entity) {
                symbolIdCodeService.setEntity(entity);
                $scope.entityType = null;
                $scope.changeEntityType(null);
            };

            $scope.changeEntityType = function (entityType) {
                symbolIdCodeService.setEntityType(entityType);
                $scope.entitySubType = null;
                $scope.changeEntitySubType(null);
            };

            function checkLimitUseTo(item) {
                if ($scope.limitUseTo && item.limitUseTo) {
                    if (($scope.entitySubType && item.limitUseTo.indexOf($scope.entitySubType.id) >= 0)
                        || ($scope.entityType && item.limitUseTo.indexOf($scope.entityType.id) >= 0)
                        || ($scope.entity && item.limitUseTo.indexOf($scope.entity.id) >= 0)) {
                        return true;
                    }
                }
                return false
            }

            function resetModifiers(currentEntity) {
                if (disableModOneFilter(currentEntity) || checkLimitUseTo($scope.sectorOneModifier)) {
                    symbolIdCodeService.setSectorOneModifier(null);
                    $scope.sectorOneModifier = symbolIdCodeService.symbId.sectorOneModifier;
                }
                if (disableModTwoFilter(currentEntity) || checkLimitUseTo($scope.sectorOneModifier)) {
                    symbolIdCodeService.setSectorTwoModifier(null);
                    $scope.sectorTwoModifier = symbolIdCodeService.symbId.sectorTwoModifier;
                }

            }

            $scope.changeEntitySubType = function (entitySubType) {
                symbolIdCodeService.setEntitySubType(entitySubType);
                $scope.currentEntity = $scope.entitySubType || $scope.entityType || $scope.entity;
                resetModifiers($scope.currentEntity);
            };

            $scope.getLabel = function (element) {
                return element.digits + " " + element.label;
            };

            $scope.saveAsPng = function () {
                function loadImages(sources, callback) {
                    var images = {};
                    var loadedImages = 0;
                    var numImages = 0;
                    // get num of sources
                    for (var src in sources) {
                        if (sources[src]) {
                            numImages++;
                        }
                    }
                    for (var src in sources) {
                        if (sources[src]) {
                            images[src] = new Image();
                            images[src].onload = function () {
                                if (++loadedImages >= numImages) {
                                    callback(images);
                                }
                            };
                            images[src].src = sources[src];
                        }
                    }
                }

                function drawImage(source) {
                    if (source) {
                        var myCanvasContext = $scope.myCanvas.getContext('2d');
                        myCanvasContext.drawImage(source, 0, 0, $scope.myCanvas.width, $scope.myCanvas.height);
                    }

                }

                if (!$scope.myCanvas) {
                    var myCanvas = document.createElement('canvas');
                    myCanvas.width = 612;
                    myCanvas.height = 792;
                    $scope.myCanvas = myCanvas;
                } else {
                    var context = $scope.myCanvas.getContext('2d');
                    context.clearRect ( 0 , 0 , $scope.myCanvas.width, $scope.myCanvas.height );
                }

                var sources = {
                    frame: $scope.frame(),
                    main: $scope.main(),
                    modifierOneFn: $scope.modifierOneFn(),
                    modifierTwoFn: $scope.modifierTwoFn(),
                    amplifierFn: $scope.amplifierFn(),
                    statusFn: $scope.statusFn(),
                    hqtfdFn: $scope.hqtfdFn()

                };

                loadImages(sources, function (images) {
                    drawImage(images.frame);
                    drawImage(images.main);
                    drawImage(images.modifierOneFn);
                    drawImage(images.modifierTwoFn);
                    drawImage(images.amplifierFn);
                    drawImage(images.statusFn);
                    drawImage(images.hqtfdFn);
                    $scope.myCanvas.toBlob(function (blob) {
                        var fileName = symbolIdCodeService.getSymbolIdentificationCode() + '.png';
                        saveAs(blob, fileName);
                    });

                });
            };

            $scope.copySic = function() {
                return symbolIdCodeService.getSymbolIdentificationCode();
            }

        }])

    .controller('SymbolIdCodeCtrl', ['$scope', 'symbolIdCodeService', function ($scope, symbolCodeIdService) {
        var sid = symbolCodeIdService.symbId;
        $scope.symbId = symbolCodeIdService.symbId;
        $scope.sid = symbolCodeIdService.getSymbolIdentificationCode;
        $scope.gget = function (name) {
            return sid[name] || {"label": "Undefined", "digits": "00"};

        };
    }])

    .filter('limitUseToModFilter', function () {
        return function (input, scope, isEnabled) {
            if (isEnabled) {
                return input.filter(function (item) {
                    if (item.limitUseTo) {
                        if ((scope.entitySubType && item.limitUseTo.indexOf(scope.entitySubType.id) >= 0)
                            || (scope.entityType && item.limitUseTo.indexOf(scope.entityType.id) >= 0)
                            || (scope.entity && item.limitUseTo.indexOf(scope.entity.id) >= 0)) {
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        return true
                    }
                });
            }
            else {
                return input;
            }
        };
    })

    .filter('disableModOne', function () {
        return function (entity) {
            switch (entity.icon) {
                case "FULL_OCTAGON":
                case "MAIN_1":
                    return true;
                default:
                    return false;
            }
            return false;
        };
    })

    .filter('disableModTwo', function () {
        return function (entity) {
            switch (entity.icon) {
                case "FULL_OCTAGON":
                case "MAIN_2":
                    return true;
                default:
                    return false;
            }
            return false;
        };
    })
;

<commit_msg>Avoid error in checkLimitUseTo if item is none<commit_after>angular.module('symbolApp')
    .factory('symbolIdCodeService', ['config', 'pathService', function (config, pathService) {
        var symbolIdCode = {};
        var undef = {"label": "Undefined", digits: "00"};
        var SVG_PATH = config.SVG_PATH;
        var alternateAmplifiers = false;
        symbolIdCode.versionCode1 = "1";
        symbolIdCode.versionCode2 = "0";
        symbolIdCode.context = symbolData.contexts[0];
        symbolIdCode.standardIdentity = symbolData.standardIdentities[3];
        symbolIdCode.symbolSet = symbolData.symbolSets[4];
        symbolIdCode.status = symbolData.statuses[0];
        symbolIdCode.hqtfDummy = symbolData.hqtfDummies[0];
        symbolIdCode.amplifier = symbolData.amplifier[1];
        symbolIdCode.amplifierDescriptor = symbolData.amplifier[1].descriptors[5];
        symbolIdCode.entity = symbolIdCode.symbolSet.entities[1];
        symbolIdCode.entityType = symbolIdCode.entity.entityTypes[2];
        symbolIdCode.entitySubType = symbolIdCode.entityType.entitySubTypes[0];
        symbolIdCode.sectorOneModifier = null;
        symbolIdCode.sectorTwoModifier = null;
        symbolIdCode.useCivilianFrame = false;

        function computeSymbolIdentificationCode() {
            var sic = symbolIdCode;
            var version = sic.versionCode1 + sic.versionCode2;
            var context = sic.context ? sic.context.digits : "0";
            var standardIdentity = sic.standardIdentity ? sic.standardIdentity.digits : "0";
            var symbolSet = sic.symbolSet ? sic.symbolSet.digits : "00";
            var status = sic.status ? sic.status.digits : "0";
            var hqtfDummy = sic.hqtfDummy ? sic.hqtfDummy.digits : "0";
            var amplifier = sic.amplifier ? sic.amplifier.digits : "0";
            var amplifierDescriptor = sic.amplifierDescriptor ? sic.amplifierDescriptor.digits : "0";
            var entity = sic.entity ? sic.entity.digits : "00";
            var entityType = sic.entityType ? sic.entityType.digits : "00";
            var entitySubType = sic.entitySubType ? sic.entitySubType.digits : "00";
            var mod1 = sic.sectorOneModifier ? sic.sectorOneModifier.digits : "00";
            var mod2 = sic.sectorTwoModifier ? sic.sectorTwoModifier.digits : "00";

            return version + context + standardIdentity + symbolSet + status + hqtfDummy + amplifier + amplifierDescriptor
                + entity + entityType + entitySubType + mod1 + mod2;

        }

        function getEntityFn() {
            var gg = symbolIdCode.entitySubType || symbolIdCode.entityType || symbolIdCode.entity;
            return pathService.getEntityFilePath(gg, symbolIdCode.symbolSet, symbolIdCode.standardIdentity.id);
        }

        function getFrameFn() {
            var sic = symbolIdCode;
            return pathService.getFrameFilePath(sic.context.id, sic.standardIdentity.id, sic.symbolSet, sic.status, sic.useCivilianFrame);
        }

        function getStatusFn() {
            var sic = symbolIdCode;
            return pathService.getStatusFilePath(sic.standardIdentity.id, sic.symbolSet, sic.status, alternateAmplifiers);
        }

        function getHqtfdFn() {
            var sic = symbolIdCode;
            return pathService.getHqtfdFilePath(sic.standardIdentity.id, sic.symbolSet, sic.hqtfDummy);
        }

        function getAmplifierFn() {
            var sic = symbolIdCode;
            return pathService.getAmplifierFilePath(sic.standardIdentity.id, sic.amplifierDescriptor);

        }

        function getModifierOneFn() {
            var fn = "";
            var sic = symbolIdCode;
            if (sic.symbolSet && sic.sectorOneModifier && sic.sectorOneModifier.digits !== "00") {
                fn = sic.symbolSet.digits + sic.sectorOneModifier.digits;
            }
            return fn ? SVG_PATH + symbolIdCode.symbolSet.graphicFolder["modifierOnes"] + "/" + fn + "1.svg" : null;
        }

        function getModifierTwoFn() {
            var fn = "";
            var sic = symbolIdCode;
            if (sic.sectorTwoModifier) {
                fn = sic.symbolSet.digits + sic.sectorTwoModifier.digits;
            }
            if (sic.sectorTwoModifier && sic.sectorTwoModifier.digits == "00") {
                return null
            }
            return fn ? SVG_PATH + symbolIdCode.symbolSet.graphicFolder["modifierTwos"] + "/" + fn + "2.svg" : null;
        }

        function getAlternateAmplifiers() {
            return alternateAmplifiers;
        }

        function setAlternateAmplifiers(alternateAmplifiersValue) {
            alternateAmplifiers = alternateAmplifiersValue;
        }

        return {
            symbId: symbolIdCode,
            getEntityFn: getEntityFn,
            getFrameFn: getFrameFn,
            getStatusFn: getStatusFn,
            getHqtfdFn: getHqtfdFn,
            getAmplifilerFn: getAmplifierFn,
            getModiferOneFn: getModifierOneFn,
            getModiferTwoFn: getModifierTwoFn,
            getAlternateAmplifiers: getAlternateAmplifiers,
            setAlternateAmplifiers: setAlternateAmplifiers,
            setStandardIdentity: function (standardIdentity) {
                symbolIdCode.standardIdentity = standardIdentity;
            },
            setContext: function (context) {
                symbolIdCode.context = context;
            },
            setSymbolSet: function (symbolSet) {
                symbolIdCode.symbolSet = symbolSet;
            },
            setStatus: function (status) {
                symbolIdCode.status = status;
            },
            setAmplifier: function (amplifer) {
                symbolIdCode.amplifier = amplifer;
            },
            setAmplifierDescriptor: function (amplifierDescriptor) {
                symbolIdCode.amplifierDescriptor = amplifierDescriptor;

            },
            setHQTFDummy: function (hqTFDummy) {
                symbolIdCode.hqtfDummy = hqTFDummy;
            },
            setEntity: function (entity) {
                symbolIdCode.entity = entity;
            },
            setEntityType: function (entityType) {
                symbolIdCode.entityType = entityType;
            },
            setEntitySubType: function (entitySubType) {
                symbolIdCode.entitySubType = entitySubType;
            },
            setSectorOneModifier: function (sectorOneModifier) {
                symbolIdCode.sectorOneModifier = sectorOneModifier || {"label": "Undefined", "digits": "00"};
            },
            setSectorTwoModifier: function (sectorTwoModifier) {
                symbolIdCode.sectorTwoModifier = sectorTwoModifier || {"label": "Undefined", "digits": "00"};
            },
            getSymbolIdentificationCode: function () {
                return computeSymbolIdentificationCode();
            }
        };
    }])

    .controller('SymbolCtrl', ['$scope', '$log', 'symbolIdCodeService', 'disableModOneFilter',
        'disableModTwoFilter', 'limitUseToModFilterFilter',
        function ($scope, $log, symbolIdCodeService, disableModOneFilter, disableModTwoFilter, limitUseToModFilterFilter) {
            $scope.frame = symbolIdCodeService.getFrameFn;
            $scope.main = symbolIdCodeService.getEntityFn;
            $scope.amplifierFn = symbolIdCodeService.getAmplifilerFn;
            $scope.modifierOneFn = symbolIdCodeService.getModiferOneFn;
            $scope.modifierTwoFn = symbolIdCodeService.getModiferTwoFn;
            $scope.statusFn = symbolIdCodeService.getStatusFn;
            $scope.hqtfdFn = symbolIdCodeService.getHqtfdFn;
            $scope.symbolData = symbolData;
            $scope.hqtfDummy = symbolIdCodeService.symbId.hqtfDummy;
            $scope.context = symbolIdCodeService.symbId.context;
            $scope.standardIdentity = symbolIdCodeService.symbId.standardIdentity;
            $scope.currentSymbolSet = symbolIdCodeService.symbId.symbolSet;
            $scope.status = symbolIdCodeService.symbId.status;
            $scope.amplifier = symbolIdCodeService.symbId.amplifier;
            $scope.amplifierDescriptor = symbolIdCodeService.symbId.amplifierDescriptor;
            $scope.symbId = symbolIdCodeService.symbId;
            $scope.ss = symbolIdCodeService;
            $scope.entity = symbolIdCodeService.symbId.entity;
            $scope.entityType = symbolIdCodeService.symbId.entityType;
            $scope.entitySubType = symbolIdCodeService.symbId.entitySubType;
            $scope.sectorOneModifier = symbolIdCodeService.symbId.sectorOneModifier;
            $scope.alternateAmplifiers = symbolIdCodeService.getAlternateAmplifiers();
            $scope.limitUseTo = true;
            $scope.currentEntity = $scope.entitySubType || $scope.entityType || $scope.entity;
            $scope.showDebugInfo = false;

            $scope.changeContext = function (context) {
                symbolIdCodeService.setContext(context);
            };

            $scope.changeStandardIdentity = function (standardIdentity) {
                symbolIdCodeService.setStandardIdentity(standardIdentity);

            };

            $scope.changeSymbolSet = function (symbolSet) {
                symbolIdCodeService.setSymbolSet(symbolSet);
                $scope.entity = null;

                $scope.entity = symbolSet.entities[0];
                $scope.changeEntity(symbolSet.entities[0]);
                $scope.sectorOneModifier = null;
                $scope.sectorTwoModifier = null;
                symbolIdCodeService.setSectorOneModifier(null);
                symbolIdCodeService.setSectorTwoModifier(null);
                $scope.amplifier = symbolData.amplifier[0];
                $scope.changeAmplifier(symbolData.amplifier[0]);

            };

            $scope.changeStatus = function (status) {
                symbolIdCodeService.setStatus(status);
            };

            $scope.changeAlternateAmplifiers = function (alternateAmplifiers) {
                symbolIdCodeService.setAlternateAmplifiers(alternateAmplifiers);
            };

            $scope.changeHQTFDummy = function (hqTfDummy) {
                symbolIdCodeService.setHQTFDummy(hqTfDummy);
            };

            $scope.changeAmplifier = function (amplifier) {
                symbolIdCodeService.setAmplifier(amplifier);
                $scope.amplifierDescriptor = amplifier.descriptors[0];
                $scope.changeAmplifierDescriptor(amplifier.descriptors[0]);
            };

            $scope.changeAmplifierDescriptor = function (amplifierDescriptor) {
                symbolIdCodeService.setAmplifierDescriptor(amplifierDescriptor);
            };

            $scope.changeEntity = function (entity) {
                symbolIdCodeService.setEntity(entity);
                $scope.entityType = null;
                $scope.changeEntityType(null);
            };

            $scope.changeEntityType = function (entityType) {
                symbolIdCodeService.setEntityType(entityType);
                $scope.entitySubType = null;
                $scope.changeEntitySubType(null);
            };

            function checkLimitUseTo(item) {
                if ($scope.limitUseTo && item && item.limitUseTo) {
                    if (($scope.entitySubType && item.limitUseTo.indexOf($scope.entitySubType.id) >= 0)
                        || ($scope.entityType && item.limitUseTo.indexOf($scope.entityType.id) >= 0)
                        || ($scope.entity && item.limitUseTo.indexOf($scope.entity.id) >= 0)) {
                        return true;
                    }
                }
                return false
            }

            function resetModifiers(currentEntity) {
                if (disableModOneFilter(currentEntity) || checkLimitUseTo($scope.sectorOneModifier)) {
                    symbolIdCodeService.setSectorOneModifier(null);
                    $scope.sectorOneModifier = symbolIdCodeService.symbId.sectorOneModifier;
                }
                if (disableModTwoFilter(currentEntity) || checkLimitUseTo($scope.sectorOneModifier)) {
                    symbolIdCodeService.setSectorTwoModifier(null);
                    $scope.sectorTwoModifier = symbolIdCodeService.symbId.sectorTwoModifier;
                }

            }

            $scope.changeEntitySubType = function (entitySubType) {
                symbolIdCodeService.setEntitySubType(entitySubType);
                $scope.currentEntity = $scope.entitySubType || $scope.entityType || $scope.entity;
                resetModifiers($scope.currentEntity);
            };

            $scope.getLabel = function (element) {
                return element.digits + " " + element.label;
            };

            $scope.saveAsPng = function () {
                function loadImages(sources, callback) {
                    var images = {};
                    var loadedImages = 0;
                    var numImages = 0;
                    // get num of sources
                    for (var src in sources) {
                        if (sources[src]) {
                            numImages++;
                        }
                    }
                    for (var src in sources) {
                        if (sources[src]) {
                            images[src] = new Image();
                            images[src].onload = function () {
                                if (++loadedImages >= numImages) {
                                    callback(images);
                                }
                            };
                            images[src].src = sources[src];
                        }
                    }
                }

                function drawImage(source) {
                    if (source) {
                        var myCanvasContext = $scope.myCanvas.getContext('2d');
                        myCanvasContext.drawImage(source, 0, 0, $scope.myCanvas.width, $scope.myCanvas.height);
                    }

                }

                if (!$scope.myCanvas) {
                    var myCanvas = document.createElement('canvas');
                    myCanvas.width = 612;
                    myCanvas.height = 792;
                    $scope.myCanvas = myCanvas;
                } else {
                    var context = $scope.myCanvas.getContext('2d');
                    context.clearRect ( 0 , 0 , $scope.myCanvas.width, $scope.myCanvas.height );
                }

                var sources = {
                    frame: $scope.frame(),
                    main: $scope.main(),
                    modifierOneFn: $scope.modifierOneFn(),
                    modifierTwoFn: $scope.modifierTwoFn(),
                    amplifierFn: $scope.amplifierFn(),
                    statusFn: $scope.statusFn(),
                    hqtfdFn: $scope.hqtfdFn()

                };

                loadImages(sources, function (images) {
                    drawImage(images.frame);
                    drawImage(images.main);
                    drawImage(images.modifierOneFn);
                    drawImage(images.modifierTwoFn);
                    drawImage(images.amplifierFn);
                    drawImage(images.statusFn);
                    drawImage(images.hqtfdFn);
                    $scope.myCanvas.toBlob(function (blob) {
                        var fileName = symbolIdCodeService.getSymbolIdentificationCode() + '.png';
                        saveAs(blob, fileName);
                    });

                });
            };

            $scope.copySic = function() {
                return symbolIdCodeService.getSymbolIdentificationCode();
            }

        }])

    .controller('SymbolIdCodeCtrl', ['$scope', 'symbolIdCodeService', function ($scope, symbolCodeIdService) {
        var sid = symbolCodeIdService.symbId;
        $scope.symbId = symbolCodeIdService.symbId;
        $scope.sid = symbolCodeIdService.getSymbolIdentificationCode;
        $scope.gget = function (name) {
            return sid[name] || {"label": "Undefined", "digits": "00"};

        };
    }])

    .filter('limitUseToModFilter', function () {
        return function (input, scope, isEnabled) {
            if (isEnabled) {
                return input.filter(function (item) {
                    if (item.limitUseTo) {
                        if ((scope.entitySubType && item.limitUseTo.indexOf(scope.entitySubType.id) >= 0)
                            || (scope.entityType && item.limitUseTo.indexOf(scope.entityType.id) >= 0)
                            || (scope.entity && item.limitUseTo.indexOf(scope.entity.id) >= 0)) {
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        return true
                    }
                });
            }
            else {
                return input;
            }
        };
    })

    .filter('disableModOne', function () {
        return function (entity) {
            switch (entity.icon) {
                case "FULL_OCTAGON":
                case "MAIN_1":
                    return true;
                default:
                    return false;
            }
            return false;
        };
    })

    .filter('disableModTwo', function () {
        return function (entity) {
            switch (entity.icon) {
                case "FULL_OCTAGON":
                case "MAIN_2":
                    return true;
                default:
                    return false;
            }
            return false;
        };
    })
;

<|endoftext|>


<commit_before>export { default } from 'smoke-and-mirrors/components/vertical-collection';
<commit_msg>remove vm-collection<commit_after><|endoftext|>


<commit_before>(function() {

  'use strict';

  smoothScroll.init();

  var scrollAnimationFlag = {
    profile:    null,
    works:      null,
    activities: null
  };

  // if a script is enabled, hide content to show with animations
  if (document.body.scrollTop < 280) {
    document.querySelector('#profile .contents-box .contents-wrapper').style.opacity = 0;
    scrollAnimationFlag['profile'] = true;
  }
  if (document.body.scrollTop < 1156) {
    document.querySelector('#works .contents-box .contents-wrapper').style.opacity = 0;
    scrollAnimationFlag['works'] = true;
  }
  if (document.body.scrollTop < 1740) {
    document.querySelector('#activities .contents-box .contents-wrapper').style.opacity = 0;
    scrollAnimationFlag['activities'] = true;
  }

  // click a down arrow to scroll down to profile content
  document.querySelector('.scroll-down').addEventListener('click', (event) => {
    event.preventDefault();
    smoothScroll.animateScroll(document.querySelector('#profile'));
  });

  // work with each scroll action
  window.addEventListener('scroll', () => {
    animateSlider(document.querySelector(   '#profile .contents-box .contents-wrapper'),  280,    'profile',  '100%');
    animateSlider(document.querySelector(     '#works .contents-box .contents-wrapper'), 1156,      'works', '-100%');
    animateSlider(document.querySelector('#activities .contents-box .contents-wrapper'), 1740, 'activities',  '100%');
  });

  // show content with slider animations
  var animateSlider = (element, position, flag, direction) => {
    if (document.body.scrollTop > position && scrollAnimationFlag[flag]) {
      element.animate({
        opacity: [0, 1],
        transform: ['translate(' + direction + ', 0)', 'translate(0, 0)'],
      }, {
        duration: 250,
        iterations: 1,
        easing: 'ease-in-out',
      }).onfinish = () => {
        element.style.opacity = 1;
        scrollAnimationFlag[flag] = false;
      }
    }
  }

}());
<commit_msg>:recycle: Recode general scripts with ES2015<commit_after>(() => {

  'use strict';

  smoothScroll.init();

  var scrollAnimationFlag = {
    profile:    null,
    works:      null,
    activities: null
  };

  // if a script is enabled, hide content to show with animations
  if (document.body.scrollTop < 280) {
    document.querySelector('#profile .contents-box .contents-wrapper').style.opacity = 0;
    scrollAnimationFlag['profile'] = true;
  }
  if (document.body.scrollTop < 1156) {
    document.querySelector('#works .contents-box .contents-wrapper').style.opacity = 0;
    scrollAnimationFlag['works'] = true;
  }
  if (document.body.scrollTop < 1740) {
    document.querySelector('#activities .contents-box .contents-wrapper').style.opacity = 0;
    scrollAnimationFlag['activities'] = true;
  }

  // click a down arrow to scroll down to profile content
  document.querySelector('.scroll-down').addEventListener('click', (event) => {
    event.preventDefault();
    smoothScroll.animateScroll(document.querySelector('#profile'));
  });

  // work with each scroll action
  window.addEventListener('scroll', () => {
    animateSlider(document.querySelector(   '#profile .contents-box .contents-wrapper'),  280,    'profile',  '100%');
    animateSlider(document.querySelector(     '#works .contents-box .contents-wrapper'), 1156,      'works', '-100%');
    animateSlider(document.querySelector('#activities .contents-box .contents-wrapper'), 1740, 'activities',  '100%');
  });

  // show content with slider animations
  var animateSlider = (element, position, flag, direction) => {
    if (document.body.scrollTop > position && scrollAnimationFlag[flag]) {
      element.animate({
        opacity: [0, 1],
        transform: ['translate(' + direction + ', 0)', 'translate(0, 0)'],
      }, {
        duration: 250,
        iterations: 1,
        easing: 'ease-in-out',
      }).onfinish = () => {
        element.style.opacity = 1;
        scrollAnimationFlag[flag] = false;
      }
    }
  }

})();
<|endoftext|>


<commit_before>;(function ( $ ) {

    /**
     * Returns a new - Progress instance
     * @param {jQuery} el - The jQuery selected elements
     * @param {Object} options - The plugin options
     * @returns {Progress}
     */
    function Progress (el, options)
    {
        var defaults = {
            url:    '?filename={filename}&progress={progress}',
            progressEl: '#progress-result',
            onBlocksize:  this.onBlocksize,
            onProgress: this.onProgress,
            onError:    this.onError
        }

        var plugin = this;

        plugin.settings = {}

        var init = function() {
            plugin.settings = $.extend({}, defaults, options);
            plugin.el       = el;
            plugin.files    = [];
            plugin.data     = [];
            plugin.ajax     = [];
        }

        // call the "constructor" method
        init();
        plugin.listen();
    }

    /**
     * Starts to listen to target element
     * @returns {Boolean}
     */
    Progress.prototype.listen = function ()
    {
        var me = this;
        if (this.el.length === 0) return false;
        this.el.on(
            'change',
            function (evt) {
                me.handleFileSelect(evt, me)
            }
        );
        return true;
    }

    /**
     * Event callback for resolving block size
     * The amount of data to be sent to server on each Ajax request
     * @param {integer} total - The total size of the file
     * @returns {integer}
     */
    Progress.prototype.onBlocksize = function(total) {
        return parseInt(total/10);
    }

    /**
     * Event callback for each time it receives an ajax response
     * @param {integer} i - The file index to be uploaded
     * @param {integer} progress - The amount of upload progress in %
     * @param {string} filename - The name of the file
     * @returns {undefined}
     */
    Progress.prototype.onProgress = function (i, progress, filename) {
        if (!$(this.progressEl+' li[class="p'+i+'"]').length) {
            $(this.progressEl).append('
');
        }
        $(this.progressEl+' li[class="p'+i+'"]').css('width', ''+progress+'%').text(filename+' '+progress+'%');
        if (progress === 100) {
            $(this.progressEl+' li[class="p'+i+'"]').fadeTo('slow', 0.5);
        }
    }

    /**
     * Event callback when an error occurs
     * @param {integer} i - The file index to be uploaded
     * @param {integer} progress - The amount of upload progress in %
     * @param {string} filename - The name of the file
     * @returns {undefined}
     */
    Progress.prototype.onError = function(i, progress, filename) {
        if (!$(this.progressEl+' li[class="p'+i+'"]').length) {
            $(this.progressEl).append('
');
        }
        $(this.progressEl+' li[class="p'+i+'"]').css('width', '100%').text(filename+' error: could not save file!');
    }

    /**
     * Utility method to slice the file
     * @param {ArrayBuffer} ab - The complete file as  ArrayBuffer
     * @param {integer} start - The start of the slice
     * @param {integer} end - The end of the slice
     * @returns {ArrayBuffer}
     */
    Progress.prototype.bufferSlice = function (ab, start, end)
    {
        var that = new Uint8Array(ab);
        if (end === undefined) {
            end = that.length;
        }
        var result = new ArrayBuffer(end - start);
        var resultArray = new Uint8Array(result);
        for (var i = 0; i < resultArray.length; i++)
           resultArray[i] = that[i + start];
        return result;
    }

    /**
     * The upload method. It creates an Ajax request to send the file slice
     * @param {integer} start - The start of the block
     * @param {integer} size - The block size
     * @param {integer} i - The file index
     * @returns {undefined}
     */
    Progress.prototype.upload = function (start, size, i)
    {
        var data = this.data[i];
        var total = data.byteLength;
        var filename = this.files[i].name;
        var progress = parseInt((start + size)/total*100);
        var part;
        var url = this.settings.url;
        url = url.replace("\{filename\}", filename, "gi");
        url = url.replace("\{progress\}", progress, "gi");
        if (window.chrome) {
            part = new DataView(this.bufferSlice(data, start, start + size));
        } else {
            part = this.bufferSlice(data, start, start + size);
        }
        this.ajax[i] = new XMLHttpRequest();
        this.ajax[i].open("POST", url, 1);
        this.ajax[i].setRequestHeader("Content-type", 'text/plain; charset=x-user-defined');
        var me = this;
        this.ajax[i].onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                var response = JSON.parse(this.responseText);
                next = start + size;
                if (!response.result) {
                    return me.settings.onError(i, progress, filename);
                }
                me.settings.onProgress(i, progress, filename);
                if (next > total) return;
                start = next;
                if (start + size > total) {
                    size = total - start;
                }
                if (size > 0) me.upload(start, size, i);
            }
        }
        this.ajax[i].send(part);
    }

    /**
     * Event callback to handle the user input
     * @param {Object} evt - The event
     * @param {Progress} me - The plugin instance
     * @returns {undefined}
     */
    Progress.prototype.handleFileSelect = function (evt, me)
    {
        console.log(evt);
        var files = evt.target.files;
        for (var i = 0, f; f = files[i]; i++) {
            me.files.push(f);
            var k = me.files.length-1;
            var reader = new FileReader();
            reader.onloadend = (function(j) {
                return function(e) {
                    me.data[j] = e.target.result;
                    var total = me.data[j].byteLength;
                    var size = me.settings.onBlocksize(total);
                    if (total < size) size = total;
                    me.upload(0, size, j);
                };
            })(k);
            reader.readAsArrayBuffer(f);
        }
    }

    /**
     * Adds Progress to jQuery plugins
     * @param {Object} options - The plugin options
     * @returns {Progress}
     */
    $.fn.Progress = function(options) {
        return new Progress(this, options);
    }

}( jQuery ));
<commit_msg>Add logging. Add better error handling.<commit_after>;(function ( $ ) {

    /**
     * Returns a new - Progress instance
     * @param {jQuery} el - The jQuery selected elements
     * @param {Object} options - The plugin options
     * @returns {Progress}
     */
    function Progress (el, options)
    {
        var defaults = {
            url:    '?filename={filename}&progress={progress}',
            progressEl: '#progress-result',
            onBlocksize:  this.onBlocksize,
            onProgress: this.onProgress,
            onError:    this.onError,
            debug:      true
        };

        var plugin = this;

        plugin.settings = {};

        var init = function() {
            //console.log(el);
            plugin.settings = $.extend({}, defaults, options);
            plugin.el       = el;
            plugin.files    = [];
            plugin.data     = [];
            plugin.ajax     = [];
        };

        // call the "constructor" method
        init();
    }

    /**
     * Displays messages in the console
     * @param {string} msg
     * @returns {Progress}
     */
    Progress.prototype.log = function(msg) {
        if (
            this.settings.debug
            && typeof console !== 'undefined'
            && typeof console.warn === 'function'
        ) {
            console.warn(msg);
        }
        return this;
    };

    /**
     * Starts to listen to target element
     * @returns {Progress}
     */
    Progress.prototype.listen = function ()
    {
        this.log('Progress: listen to '+$(this.el).selector);
        var me = this;
        $(this.el).on('change', function (evt) {me.handleFileSelect(evt, me)});
        return this;
    };

    /**
     * Event callback for resolving block size
     * The amount of data to be sent to server on each Ajax request
     * @param {integer} total - The total size of the file
     * @returns {integer}
     */
    Progress.prototype.onBlocksize = function(total) {
        return parseInt(total/10);
    }

    /**
     * Event callback for each time it receives an ajax response
     * @param {integer} i - The file index to be uploaded
     * @param {integer} progress - The amount of upload progress in %
     * @param {string} filename - The name of the file
     * @returns {undefined}
     */
    Progress.prototype.onProgress = function (i, progress, filename) {
        if (!$(this.progressEl+' li[class="p'+i+'"]').length) {
            $(this.progressEl).append('
');
        }
        $(this.progressEl+' li[class="p'+i+'"]').css('width', ''+progress+'%').text(filename+' '+progress+'%');
        if (progress === 100) {
            $(this.progressEl+' li[class="p'+i+'"]').fadeTo('slow', 0.5);
        }
    }

    /**
     * Event callback when an error occurs
     * @param {integer} i - The file index to be uploaded
     * @param {integer} progress - The amount of upload progress in %
     * @param {string} filename - The name of the file
     * @returns {undefined}
     */
    Progress.prototype.onError = function(i, progress, filename) {
        if (!$(this.progressEl+' li[class="p'+i+'"]').length) {
            $(this.progressEl).append('
');
        }
        $(this.progressEl+' li[class="p'+i+'"]').css('width', '100%').text(filename+' error: could not save file!');
    }

    /**
     * Utility method to slice the file
     * @param {ArrayBuffer} ab - The complete file as  ArrayBuffer
     * @param {integer} start - The start of the slice
     * @param {integer} end - The end of the slice
     * @returns {ArrayBuffer}
     */
    Progress.prototype.bufferSlice = function (ab, start, end)
    {
        var that = new Uint8Array(ab);
        if (end === undefined) {
            end = that.length;
        }
        var result = new ArrayBuffer(end - start);
        var resultArray = new Uint8Array(result);
        for (var i = 0; i < resultArray.length; i++)
           resultArray[i] = that[i + start];
        return result;
    }

    /**
     * The upload method. It creates an Ajax request to send the file slice
     * @param {integer} start - The start of the block
     * @param {integer} size - The block size
     * @param {integer} i - The file index
     * @returns {undefined}
     */
    Progress.prototype.upload = function (start, size, i)
    {
        var data = this.data[i];
        var total = data.byteLength;
        var filename = this.files[i].name;
        var progress = parseInt((start + size)/total*100);
        var part;
        var url = this.settings.url;
        url = url.replace("\{filename\}", filename, "gi");
        url = url.replace("\{progress\}", progress, "gi");
        if (window.chrome) {
            part = new DataView(this.bufferSlice(data, start, start + size));
        } else {
            part = this.bufferSlice(data, start, start + size);
        }
        this.ajax[i] = new XMLHttpRequest();
        this.ajax[i].open("POST", url, 1);
        this.ajax[i].setRequestHeader("Content-type", 'text/plain; charset=x-user-defined');
        var me = this;
        this.ajax[i].onreadystatechange = function() {
            if (this.readyState === 4) {
                if (this.status !== 200) {
                    me.log('Progress: something went wrong!');
                } else {
                    var response = JSON.parse(this.responseText);
                    next = start + size;
                    if (!response.result) {
                        return me.settings.onError(i, progress, filename);
                    }
                    me.settings.onProgress(i, progress, filename);
                    if (next > total) return;
                    start = next;
                    if (start + size > total) {
                        size = total - start;
                    }
                    if (size > 0) {
                        me.upload(start, size, i);
                    } else {
                        me.log('Progress: '+me.files[i].name+' complete!');
                    }
                }
            }
        }
        this.ajax[i].send(part);
    }

    /**
     * Event callback to handle the user input
     * @param {Object} evt - The event
     * @param {Progress} me - The plugin instance
     * @returns {undefined}
     */
    Progress.prototype.handleFileSelect = function (evt, me)
    {
        this.log('Progress: get files information...');
        var files = evt.target.files;
        for (var i = 0, f; f = files[i]; i++) {
            me.files.push(f);
            var k = me.files.length-1;
            var reader = new FileReader();
            reader.onloadend = (function(j) {
                return function(e) {
                    me.data[j] = e.target.result;
                    var total = me.data[j].byteLength;
                    var size = me.settings.onBlocksize(total);
                    if (total < size) size = total;
                    me.log('Progress: start progress for '+me.files[j].name);
                    me.upload(0, size, j);
                };
            })(k);
            reader.readAsArrayBuffer(f);
        }
    }

    /**
     * Adds Progress to jQuery plugins
     * @param {Object} options - The plugin options
     * @returns {Progress}
     */
    $.fn.Progress = function(options) {
        var p = new Progress(this, options);
        if (this.length === 0) {
            p.log('Progress: invalid target '+this.selector+'. Aborting');
            return false;
        }
        p.listen();
        return p;
    }

}( jQuery ));
<|endoftext|>


<commit_before>var rule = 'no-dupe-scenario-names';
var scenarios = [];
var availableConfigs = [
  'anywhere',
  'in-feature'
];

function noDuplicateScenarioNames(feature, file, configuration) {
  if(configuration === 'in-feature') {
    scenarios = [];
  }
  if(feature.children) {
    var errors = [];
    feature.children.forEach(function(scenario) {
      if (scenario.name) {
        if (scenario.name in scenarios) {
          var dupes = getFileLinePairsAsStr(scenarios[scenario.name].locations);
          scenarios[scenario.name].locations.push({file: file.name, line: scenario.location.line});
          errors.push({message: 'Scenario name is already used in: ' + dupes,
            rule   : rule,
            line   : scenario.location.line});
        } else {
          scenarios[scenario.name] = {locations: [{file: file.name, line: scenario.location.line}]};
        }
      }
    });
    return errors;
  }
}

function getFileLinePairsAsStr(objects) {
  var strings = [];
  objects.forEach(function(object) {
    strings.push(object.file + ':' + object.line);
  });
  return strings.join(', ');
}

module.exports = {
  name: rule,
  run: noDuplicateScenarioNames,
  reset: () => scenarios = [],
  availableConfigs: availableConfigs
};
<commit_msg>relaunch check after conflict solved<commit_after>var rule = 'no-dupe-scenario-names';
var scenarios = [];
var availableConfigs = [
  'anywhere',
  'in-feature'
];

function noDuplicateScenarioNames(feature, file, configuration) {
  if(configuration === 'in-feature') {
    scenarios = [];
  }
  if(feature.children) {
    var errors = [];

    feature.children.forEach(function(scenario) {
      if (scenario.name) {
        if (scenario.name in scenarios) {
          var dupes = getFileLinePairsAsStr(scenarios[scenario.name].locations);
          scenarios[scenario.name].locations.push({file: file.name, line: scenario.location.line});
          errors.push({message: 'Scenario name is already used in: ' + dupes,
            rule   : rule,
            line   : scenario.location.line});
        } else {
          scenarios[scenario.name] = {locations: [{file: file.name, line: scenario.location.line}]};
        }
      }
    });
    return errors;
  }
}

function getFileLinePairsAsStr(objects) {
  var strings = [];
  objects.forEach(function(object) {
    strings.push(object.file + ':' + object.line);
  });
  return strings.join(', ');
}

module.exports = {
  name: rule,
  run: noDuplicateScenarioNames,
  reset: () => scenarios = [],
  availableConfigs: availableConfigs
};
<|endoftext|>


<commit_before>import 'bootstrap/dist/js/bootstrap'
import 'bootstrap-datepicker/dist/js/bootstrap-datepicker.min'
import Chart from 'chart.js';

import '../stylesheets/dashboard'

$(function () {
  let cal = $('#calendar');
  let currentDate = cal.val();

  cal.datepicker({
    autoclose: true,
    startDate: cal.data('start-date'),
    endDate: cal.data('end-date'),
    format: 'yyyy-mm-dd',
    todayHighlight: true
  });

  let drawScores = function (date) {
    $.ajax({
      type: 'GET',
      dataType: 'json',
      contentType: 'application/json; charset=UTF-8',
      url: Routes.endpoint_index_path({date: date}),
      timeout: 10000 // 10 sec
    }).done(function (json, textStatus, jqXHR) {
      drawBars(json.data);
      drawTable(json.data);
      currentDate = date;
    }).fail(function (jqXHR, textStatus, errorThrown) {
      window.alert(`${textStatus}: ${jqXHR.status} ${errorThrown}`);
      cal.val(currentDate);
    });
  };

  let barChart = new Chart($('#score-bar'), {
    type: 'bar',
    data: {
      labels: ['Rank A', 'Rank B', 'Rank C', 'Rank D', 'Rank E'],
      datasets: [
        {
          data: [],
          backgroundColor: ['#FF3D7F', '#3FB8AF', '#7FC7AF', '#FF9E9D', '#DAD8A7']
        }
      ],
      options: {}
    },
    options: {
      animation: {
        duration: 1000,
        easing: 'easeOutQuart',
      },
      legend: {
        display: false
      },
      scales: {
        yAxes: [{
          gridLines: {
            display: false
          },
          ticks: {
            min: 0
          }
        }]
      }
    }
  });

  let drawBars = function (json) {
    let data = json.reduce(function (memo, x) {
      memo[x.rank] += 1;

      return memo;
    }, {A: 0, B: 0, C: 0, D: 0, E: 0});

    barChart.data.datasets[0].data = Object.values(data);
    barChart.update();
  };

  let score_desc = function (a, b) {
    if (a.score > b.score) return -1;
    if (a.score < b.score) return 1;
    return 0;
  };

  let drawTable = function (json) {
    let table = $('tbody#score-table');

    table.fadeOut(500);

    let html = '';
    json.sort(score_desc).slice(0, 5).forEach(function (x, i) {
      html += '
';
      html += `<td>${x.score}</td>`;
      html += `<td><a href="${x.endpoint_url}">${x.name}</a></td>`;
      html += `<td><a href="${x.endpoint_url}" target="_blank">${x.endpoint_url}</a></td>`;
      html += '
';
    });

    table.html(html);
    table.fadeIn(500);
  };

  $('#update-date').on('click', function () {
    drawScores(cal.val());
  });

  $('#scores').carousel({
    interval: 10000
  });

  drawScores(currentDate);
});
<commit_msg>fix anchor link for endpoint name<commit_after>import 'bootstrap/dist/js/bootstrap'
import 'bootstrap-datepicker/dist/js/bootstrap-datepicker.min'
import Chart from 'chart.js';

import '../stylesheets/dashboard'

$(function () {
  let cal = $('#calendar');
  let currentDate = cal.val();

  cal.datepicker({
    autoclose: true,
    startDate: cal.data('start-date'),
    endDate: cal.data('end-date'),
    format: 'yyyy-mm-dd',
    todayHighlight: true
  });

  let drawScores = function (date) {
    $.ajax({
      type: 'GET',
      dataType: 'json',
      contentType: 'application/json; charset=UTF-8',
      url: Routes.endpoint_index_path({date: date}),
      timeout: 10000 // 10 sec
    }).done(function (json, textStatus, jqXHR) {
      drawBars(json.data);
      drawTable(json.data, json.date.current);
      currentDate = date;
    }).fail(function (jqXHR, textStatus, errorThrown) {
      window.alert(`${textStatus}: ${jqXHR.status} ${errorThrown}`);
      cal.val(currentDate);
    });
  };

  let barChart = new Chart($('#score-bar'), {
    type: 'bar',
    data: {
      labels: ['Rank A', 'Rank B', 'Rank C', 'Rank D', 'Rank E'],
      datasets: [
        {
          data: [],
          backgroundColor: ['#FF3D7F', '#3FB8AF', '#7FC7AF', '#FF9E9D', '#DAD8A7']
        }
      ],
      options: {}
    },
    options: {
      animation: {
        duration: 1000,
        easing: 'easeOutQuart',
      },
      legend: {
        display: false
      },
      scales: {
        yAxes: [{
          gridLines: {
            display: false
          },
          ticks: {
            min: 0
          }
        }]
      }
    }
  });

  let drawBars = function (json) {
    let data = json.reduce(function (memo, x) {
      memo[x.rank] += 1;

      return memo;
    }, {A: 0, B: 0, C: 0, D: 0, E: 0});

    barChart.data.datasets[0].data = Object.values(data);
    barChart.update();
  };

  let score_desc = function (a, b) {
    if (a.score > b.score) return -1;
    if (a.score < b.score) return 1;
    return 0;
  };

  let drawTable = function (json, date) {
    let table = $('tbody#score-table');

    table.fadeOut(500);

    let html = '';
    json.sort(score_desc).slice(0, 5).forEach(function (x, i) {
      html += '
';
      html += `<td>${x.score}</td>`;
      html += `<td><a href="${Routes.endpoint_path({id: x.id}, {date: date})}">${x.name}</a></td>`;
      html += `<td><a href="${x.endpoint_url}" target="_blank">${x.endpoint_url}</a></td>`;
      html += '
';
    });

    table.html(html);
    table.fadeIn(500);
  };

  $('#update-date').on('click', function () {
    drawScores(cal.val());
  });

  $('#scores').carousel({
    interval: 10000
  });

  drawScores(currentDate);
});
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015-2018 by Arena of Titans Contributors.
 *
 * This file is part of Arena of Titans.
 *
 * Arena of Titans is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Arena of Titans is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Arena of Titans. If not, see <http://www.gnu.org/licenses/>.
 */

import { inject } from "aurelia-framework";
import { Store } from "aurelia-store";
import { AssetSource } from "../../services/assets";
import { EventAggregatorSubscriptions } from "./utils";
import { Popup } from "./popup";
import { Notify } from "./notify";

const PLAYER_TRANSITION_POPUP_DISPLAY_TIME = 2800;

@inject(Popup, EventAggregatorSubscriptions, Store, Notify)
export class Animations {
    constructor(popup, eas, store, notify) {
        this._popup = popup;
        this._eas = eas;
        this._store = store;
        this._notify = notify;
        this.game = {};
        this.myIndex = -1;

        this._playedAnimationForAction = 0;
        this._currentPlayerIndex = null;
    }

    enable() {
        // We disable just to be sure there are no listeners registered.
        // If we don't, we may register them twice.
        this.disable();

        this._subscription = this._store.state.subscribe(state => {
            this.game = state.game;
            this.myIndex = state.me.index;
            if (
                this.game.players &&
                !this.game.isOver &&
                (this.game.currentPlayerIndex !== this._currentPlayerIndex ||
                    this._currentNbTurns !== this.game.nbTurns)
            ) {
                this._currentPlayerIndex = this.game.currentPlayerIndex;
                this._currentNbTurns = this.game.nbTurns;
                this._playTransitionAnimation();
            } else if (
                this.game.actions &&
                this.game.actions[this.game.actions.length - 1].trump &&
                this.game.actions.length > this._playedAnimationForAction
            ) {
                this._playedAnimationForAction = this.game.actions.length;
                this._playTrumpAnimation(this.game.actions[this.game.actions.length - 1]);
            } else if (
                this.game.actions &&
                this.game.actions[this.game.actions.length - 1].specialAction &&
                this.game.actions.length > this._playedAnimationForAction
            ) {
                this._playedAnimationForAction = this.game.actions.length;
                this._playSpecialActionAnimation(this.game.actions[this.game.actions.length - 1]);
            }
        });
    }

    _playSpecialActionAnimation(action) {
        let popupData = {
            translate: {
                messages: {},
            },
        };

        let initiatorHero = this.game.players[action.initiator.index].hero;
        popupData.initiatorHeroImg = AssetSource.forHero(initiatorHero);
        popupData.translate.messages.playerName = this.game.players[this._currentPlayerIndex].name;
        popupData.assassinImg = AssetSource.forAnimation({
            name: action.specialAction.trumpArgs.name,
            color: action.specialAction.trumpArgs.color,
        });

        let targetHero = this.game.players[action.target.index].hero;
        popupData.targetedHeroImg = AssetSource.forHero(targetHero);
        popupData.translate.messages.targetName = this.game.players[action.target.index].name;

        let options = {
            timeout: PLAYER_TRANSITION_POPUP_DISPLAY_TIME,
        };

        this._popup.display("assassination-animation", popupData, options);
    }

    _playTransitionAnimation() {
        let popupData = {
            translate: {
                messages: {},
            },
        };
        if (this._currentPlayerIndex !== this.myIndex) {
            popupData.translate.messages.message = "game.play.whose_turn_message";
            popupData.htmlMessage = true;
        } else {
            popupData.translate.messages.message = "game.play.your_turn";
            this._notify.notifyYourTurn();
        }
        let hero = this.game.players[this.game.currentPlayerIndex].hero;
        popupData.img = AssetSource.forChestHero(hero);
        popupData.translate.params = {
            playerName: this.game.players[this._currentPlayerIndex].name,
        };

        let options = {
            timeout: PLAYER_TRANSITION_POPUP_DISPLAY_TIME,
        };
        this._popup.display("transition", popupData, options);
    }

    _playTrumpAnimation(action) {
        let popupData = {
            translate: {
                messages: {},
            },
        };

        let initiatorHero = this.game.players[action.initiator.index].hero;
        popupData.initiatorHeroImg = AssetSource.forHero(initiatorHero);
        popupData.translate.messages.playerName = this.game.players[this._currentPlayerIndex].name;
        let trump1 = action.trump;
        popupData.trumpImg = AssetSource.forTrump(trump1);
        popupData.translate.messages.trumpName = action.trump.name;

        // Power-ups are when a trump is played on the initiator (ie player == target)
        if (action.description === "played_trump_no_effect") {
            popupData.kind = "failed";
        } else if (action.initiator.index === action.target.index) {
            popupData.kind = "powerup";
        } else {
            popupData.kind = "smash";

            let targetHero = this.game.players[action.target.index].hero;
            popupData.targetedHeroImg = AssetSource.forHero(targetHero);
            popupData.translate.messages.targetName = this.game.players[action.target.index].name;
        }

        let options = {
            timeout: PLAYER_TRANSITION_POPUP_DISPLAY_TIME,
        };

        this._popup.display("trump-animation", popupData, options);
    }

    disable() {
        this._eas.dispose();

        if (this._subscription) {
            this._subscription.unsubscribe();
        }
    }
}
<commit_msg>fix(animation): display power image in trump aninmation when a power is played<commit_after>/*
 * Copyright (C) 2015-2018 by Arena of Titans Contributors.
 *
 * This file is part of Arena of Titans.
 *
 * Arena of Titans is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Arena of Titans is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Arena of Titans. If not, see <http://www.gnu.org/licenses/>.
 */

import { inject } from "aurelia-framework";
import { Store } from "aurelia-store";
import { AssetSource } from "../../services/assets";
import { EventAggregatorSubscriptions } from "./utils";
import { Popup } from "./popup";
import { Notify } from "./notify";

const PLAYER_TRANSITION_POPUP_DISPLAY_TIME = 2800;

@inject(Popup, EventAggregatorSubscriptions, Store, Notify)
export class Animations {
    constructor(popup, eas, store, notify) {
        this._popup = popup;
        this._eas = eas;
        this._store = store;
        this._notify = notify;
        this.game = {};
        this.myIndex = -1;

        this._playedAnimationForAction = 0;
        this._currentPlayerIndex = null;
    }

    enable() {
        // We disable just to be sure there are no listeners registered.
        // If we don't, we may register them twice.
        this.disable();

        this._subscription = this._store.state.subscribe(state => {
            this.game = state.game;
            this.myIndex = state.me.index;
            if (
                this.game.players &&
                !this.game.isOver &&
                (this.game.currentPlayerIndex !== this._currentPlayerIndex ||
                    this._currentNbTurns !== this.game.nbTurns)
            ) {
                this._currentPlayerIndex = this.game.currentPlayerIndex;
                this._currentNbTurns = this.game.nbTurns;
                this._playTransitionAnimation();
            } else if (
                this.game.actions &&
                this.game.actions[this.game.actions.length - 1].trump &&
                this.game.actions.length > this._playedAnimationForAction
            ) {
                this._playedAnimationForAction = this.game.actions.length;
                this._playTrumpAnimation(this.game.actions[this.game.actions.length - 1]);
            } else if (
                this.game.actions &&
                this.game.actions[this.game.actions.length - 1].specialAction &&
                this.game.actions.length > this._playedAnimationForAction
            ) {
                this._playedAnimationForAction = this.game.actions.length;
                this._playSpecialActionAnimation(this.game.actions[this.game.actions.length - 1]);
            }
        });
    }

    _playSpecialActionAnimation(action) {
        let popupData = {
            translate: {
                messages: {},
            },
        };

        let initiatorHero = this.game.players[action.initiator.index].hero;
        popupData.initiatorHeroImg = AssetSource.forHero(initiatorHero);
        popupData.translate.messages.playerName = this.game.players[this._currentPlayerIndex].name;
        popupData.assassinImg = AssetSource.forAnimation({
            name: action.specialAction.trumpArgs.name,
            color: action.specialAction.trumpArgs.color,
        });

        let targetHero = this.game.players[action.target.index].hero;
        popupData.targetedHeroImg = AssetSource.forHero(targetHero);
        popupData.translate.messages.targetName = this.game.players[action.target.index].name;

        let options = {
            timeout: PLAYER_TRANSITION_POPUP_DISPLAY_TIME,
        };

        this._popup.display("assassination-animation", popupData, options);
    }

    _playTransitionAnimation() {
        let popupData = {
            translate: {
                messages: {},
            },
        };
        if (this._currentPlayerIndex !== this.myIndex) {
            popupData.translate.messages.message = "game.play.whose_turn_message";
            popupData.htmlMessage = true;
        } else {
            popupData.translate.messages.message = "game.play.your_turn";
            this._notify.notifyYourTurn();
        }
        let hero = this.game.players[this.game.currentPlayerIndex].hero;
        popupData.img = AssetSource.forChestHero(hero);
        popupData.translate.params = {
            playerName: this.game.players[this._currentPlayerIndex].name,
        };

        let options = {
            timeout: PLAYER_TRANSITION_POPUP_DISPLAY_TIME,
        };
        this._popup.display("transition", popupData, options);
    }

    _playTrumpAnimation(action) {
        let popupData = {
            translate: {
                messages: {},
            },
        };

        let initiatorHero = this.game.players[action.initiator.index].hero;
        popupData.initiatorHeroImg = AssetSource.forHero(initiatorHero);
        popupData.translate.messages.playerName = this.game.players[this._currentPlayerIndex].name;
        let trump1 = action.trump;
        if (trump1.passive !== undefined) {
            popupData.trumpImg = AssetSource.forPower(trump1.trumpArgs);
        } else {
            popupData.trumpImg = AssetSource.forTrump(trump1);
        }
        popupData.translate.messages.trumpName = action.trump.name;

        // Power-ups are when a trump is played on the initiator (ie player == target)
        if (action.description === "played_trump_no_effect") {
            popupData.kind = "failed";
        } else if (action.initiator.index === action.target.index) {
            popupData.kind = "powerup";
        } else {
            popupData.kind = "smash";

            let targetHero = this.game.players[action.target.index].hero;
            popupData.targetedHeroImg = AssetSource.forHero(targetHero);
            popupData.translate.messages.targetName = this.game.players[action.target.index].name;
        }

        let options = {
            timeout: PLAYER_TRANSITION_POPUP_DISPLAY_TIME,
        };

        this._popup.display("trump-animation", popupData, options);
    }

    disable() {
        this._eas.dispose();

        if (this._subscription) {
            this._subscription.unsubscribe();
        }
    }
}
<|endoftext|>


<commit_before>var debug = require("debug")("blot:helper:transformer");
var client = require("models/client");
var isURL = require("./isURL");
var Keys = require("./keys");
var HashFile = require("./hash");
var download = require("./download");
var ensure = require("../ensure");
var fs = require("fs-extra");
var localPath = require("../localPath");
var config = require("config");
var join = require("path").join;
var async = require("async");
var resolveCaseInsensitivePathToFile = require("./resolveCaseInsensitivePathToFile");

// TODO:
// Fix bug with transformer to handle ESOCKETIMEDOUT error...

// Maps https://blotcdn.com/blog_xyz/_image_cache/abc.jpg to
// /_image_cache/abc.jpg to enable us to look up the file quickly
// on disk without making an HTTP request
function resolveCDNPath(src) {
  if (src.indexOf(config.cdn.origin) !== 0) return src;

  try {
    // First we remove the protocol and CDN host
    src = src.slice(config.cdn.origin.length);

    // Now we remove the blog ID from the path on the CDN
    src = src.split("/").slice(2).join("/");
    return src;
  } catch (e) {
    return src;
  }
}

function Transformer(blogID, name) {
  ensure(blogID, "string").and(name, "string");

  var keys = Keys(blogID, name);

  function lookup(src, transform, callback) {
    src = resolveCDNPath(src);

    var url = isURL(src);
    var path = src;
    var decodedURI;
    var fullLocalPath;
    var tasks = [];

    debug(src);

    // We check URLs first since isPath is less strict
    if (url) {
      debug(src, "seemes to be a URL");
      return fromURL(url, transform, callback);
    }

    if (path.length > 300) {
      return callback(new Error("Transformer: source too long: " + clip(src)));
    }

    if (path.indexOf("data:") === 0) {
      return callback(new Error("Transformer: source is unsupported protocol"));
    }

    // We try and look up the URI-decoded version of a path
    // to map "/Hello%20world.txt" to "/Hello word.txt".
    try {
      decodedURI = decodeURI(path);
    } catch (e) {
      // Can throw an error for a malformed path
      decodedURI = null;
    }

    // Images pulled from Word Documents are stored in the static folder
    tasks.push(function (next) {
      fullLocalPath = join(config.blog_static_files_dir, blogID, src);
      fromPath(fullLocalPath, transform, next);
    });

    // If we make it here, the file doesn't match anything in the static
    // folder. We don't need to look further inside the static folder since
    // those paths are added by Blot and guaranteed correct and lowercase.

    // First we check if this path matches a file in the blog folder exactly.
    tasks.push(function (next) {
      fullLocalPath = localPath(blogID, path);
      fromPath(fullLocalPath, transform, next);
    });

    // Next we attempt to resolve the path case-insensitively
    tasks.push(function (next) {
      resolveCaseInsensitivePathToFile(localPath(blogID, "/"), path, function (
        err,
        fullLocalPath
      ) {
        if (err) return next(err);
        fromPath(fullLocalPath, transform, next);
      });
    });

    // Finally we attempt to resolve the URI-decoded path case-insensitively
    if (decodedURI)
      tasks.push(function (next) {
        resolveCaseInsensitivePathToFile(
          localPath(blogID, "/"),
          decodedURI,
          function (err, fullLocalPath) {
            if (err) return next(err);
            fromPath(fullLocalPath, transform, next);
          }
        );
      });

    // Will work down the list of paths. If one of the paths
    // works then it'll stop and return the result!
    async.tryEach(tasks, function (err, results) {
      if (err) return callback(err);
      debug(results);
      callback(null, results[0], results[1]);
    });
  }

  // callback must be passed an error or null and result
  function fromURL(url, transform, callback) {
    var tasks = [];

    // Look in the database to see if we have downloaded
    // this URL in the past. If so, retrieve the response
    // headers, hash of the file's content and the result
    // application of the 'transform' called 'result'
    getURL(url, function (err, headers, hash, result) {
      if (err) return callback(err);

      // Right now ampersands in URL queries are escaped
      // which isn't ideal and breaks the thumbnail generator.
      // So we try the URL with unescaped ampersands first.
      if (url.indexOf("&") > -1) {
        tasks.push(function (next) {
          download(url.split("&").join("&"), headers, next);
        });
      }

      tasks.push(function (next) {
        download(url, headers, next);
      });

      async.tryEach(tasks, function (err, results) {
        // Now we try and download the URL, passing in previously
        // stored headers if any. This module interprets 304
        // responses nicely.
        if (err) return callback(err);

        var path = results[0];

        headers = results[1];

        // We didn't redownload the file since it's
        if (!path && result) return callback(null, result);

        // Something went wrong, if there is no path, no error
        // and no result. So leave before breaking shit.
        if (!path && !result) return callback(missing(url));

        fromPath(path, transform, function (err, result, hash) {
          // The file was downloaded to the temp
          // directory so we remove it now...
          // do this before handling any errors...
          fs.remove(path);

          if (err) return callback(err);

          setURL(url, headers, hash, result, function (err) {
            if (err) throw err;

            callback(err, result);
          });
        });
      });
    });
  }

  function fromPath(path, transform, callback) {
    ensure(path, "string").and(transform, "function").and(callback, "function");

    debug(path, "hashing file");

    HashFile(path, function (err, hash) {
      if (err) return callback(err);

      debug(path, "getting existing result from hash");
      get(hash, function (err, result) {
        // Leave early, please pass hash so that
        // from URL doesn't have to compute it again
        if (err || result) return callback(err, result, hash);

        debug(path, "transforming new file");
        transform(path, function (err, result) {
          if (err) return callback(err);

          // Pass hash so that
          // from URL doesn't have to compute it again
          debug(path, "saving result of new transform");
          set(hash, result, function (err) {
            if (err) throw err;

            callback(err, result, hash);
          });
        });
      });
    });
  }

  function getURL(url, callback) {
    var info = [keys.url.headers(url), keys.url.content(url)];

    client.mget(info, function (err, res) {
      if (err) throw err;

      var headers = null;
      var hash = null;

      try {
        headers = JSON.parse(res[0]);
        hash = res[1];
      } catch (e) {}

      if (hash === null) return callback(err, headers, hash, null);

      get(hash, function (err, result) {
        callback(err, headers, hash, result);
      });
    });
  }

  function get(hash, callback) {
    client.get(keys.content(hash), function (err, stringifiedResult) {
      if (err) throw err;

      var res = null;

      try {
        res = JSON.parse(stringifiedResult);
      } catch (e) {}

      return callback(null, res);
    });
  }

  function setURL(url, headers, hash, result, callback) {
    callback = callback || nothing;

    ensure(url, "string")
      .and(headers, "object")
      .and(hash, "string")
      .and(result, "object")
      .and(callback, "function");

    var urlContentKey = keys.url.content(url);
    var urlHeadersKey = keys.url.headers(url);
    var contentKey = keys.content(hash);

    var stringifiedHeaders = JSON.stringify(headers);
    var stringifiedResult = JSON.stringify(result);

    client
      .multi()
      .sadd(keys.everything, contentKey, urlContentKey, urlHeadersKey)
      .mset(
        urlContentKey,
        hash,
        urlHeadersKey,
        stringifiedHeaders,
        contentKey,
        stringifiedResult
      )
      .exec(callback);
  }

  function set(hash, result, callback) {
    callback = callback || nothing;

    ensure(hash, "string").and(result, "object").and(callback, "function");

    var stringifiedResult = JSON.stringify(result);
    var contentKey = keys.content(hash);

    client
      .multi()
      .sadd(keys.everything, contentKey)
      .set(contentKey, stringifiedResult)
      .exec(callback);
  }

  function flush(callback) {
    client.smembers(keys.everything, function (err, keys) {
      client.del(keys, function () {
        callback();
      });
    });
  }

  return {
    lookup: lookup,
    flush: flush,
  };
}

function nothing(err) {
  if (err) throw err;
}

function missing(src) {
  return new Error("Transformer: URL could not be downloaded: " + clip(src));
}

function clip(src) {
  if (src.length > 50)
    src =
      src.slice(0, 50) + "... (" + (src.length - 50) + " characters removed)";
  return src;
}

module.exports = Transformer;
<commit_msg>Handle incorrect type of arguments passed to transformer<commit_after>var debug = require("debug")("blot:helper:transformer");
var client = require("models/client");
var isURL = require("./isURL");
var Keys = require("./keys");
var HashFile = require("./hash");
var download = require("./download");
var type = require("../type");
var ensure = require("../ensure");
var fs = require("fs-extra");
var localPath = require("../localPath");
var config = require("config");
var join = require("path").join;
var async = require("async");
var resolveCaseInsensitivePathToFile = require("./resolveCaseInsensitivePathToFile");

// TODO:
// Fix bug with transformer to handle ESOCKETIMEDOUT error...

// Maps https://blotcdn.com/blog_xyz/_image_cache/abc.jpg to
// /_image_cache/abc.jpg to enable us to look up the file quickly
// on disk without making an HTTP request
function resolveCDNPath(src) {
  if (src.indexOf(config.cdn.origin) !== 0) return src;

  try {
    // First we remove the protocol and CDN host
    src = src.slice(config.cdn.origin.length);

    // Now we remove the blog ID from the path on the CDN
    src = src.split("/").slice(2).join("/");
    return src;
  } catch (e) {
    return src;
  }
}

function Transformer(blogID, name) {
  ensure(blogID, "string").and(name, "string");

  var keys = Keys(blogID, name);

  function lookup(src, transform, callback) {
    if (type(src) !== "string") {
      return callback(new Error("Transformer: src is not a string"));
    }

    if (type(transform) !== "function") {
      return callback(new Error("Transformer: transformer is not a function"));
    }

    src = resolveCDNPath(src);

    var url = isURL(src);
    var path = src;
    var decodedURI;
    var fullLocalPath;
    var tasks = [];

    debug(src);

    // We check URLs first since isPath is less strict
    if (url) {
      debug(src, "seemes to be a URL");
      return fromURL(url, transform, callback);
    }

    if (path.length > 300) {
      return callback(new Error("Transformer: source too long: " + clip(src)));
    }

    if (path.indexOf("data:") === 0) {
      return callback(new Error("Transformer: source is unsupported protocol"));
    }

    // We try and look up the URI-decoded version of a path
    // to map "/Hello%20world.txt" to "/Hello word.txt".
    try {
      decodedURI = decodeURI(path);
    } catch (e) {
      // Can throw an error for a malformed path
      decodedURI = null;
    }

    // Images pulled from Word Documents are stored in the static folder
    tasks.push(function (next) {
      fullLocalPath = join(config.blog_static_files_dir, blogID, src);
      fromPath(fullLocalPath, transform, next);
    });

    // If we make it here, the file doesn't match anything in the static
    // folder. We don't need to look further inside the static folder since
    // those paths are added by Blot and guaranteed correct and lowercase.

    // First we check if this path matches a file in the blog folder exactly.
    tasks.push(function (next) {
      fullLocalPath = localPath(blogID, path);
      fromPath(fullLocalPath, transform, next);
    });

    // Next we attempt to resolve the path case-insensitively
    tasks.push(function (next) {
      resolveCaseInsensitivePathToFile(localPath(blogID, "/"), path, function (
        err,
        fullLocalPath
      ) {
        if (err) return next(err);
        fromPath(fullLocalPath, transform, next);
      });
    });

    // Finally we attempt to resolve the URI-decoded path case-insensitively
    if (decodedURI)
      tasks.push(function (next) {
        resolveCaseInsensitivePathToFile(
          localPath(blogID, "/"),
          decodedURI,
          function (err, fullLocalPath) {
            if (err) return next(err);
            fromPath(fullLocalPath, transform, next);
          }
        );
      });

    // Will work down the list of paths. If one of the paths
    // works then it'll stop and return the result!
    async.tryEach(tasks, function (err, results) {
      if (err) return callback(err);
      debug(results);
      callback(null, results[0], results[1]);
    });
  }

  // callback must be passed an error or null and result
  function fromURL(url, transform, callback) {
    var tasks = [];

    // Look in the database to see if we have downloaded
    // this URL in the past. If so, retrieve the response
    // headers, hash of the file's content and the result
    // application of the 'transform' called 'result'
    getURL(url, function (err, headers, hash, result) {
      if (err) return callback(err);

      // Right now ampersands in URL queries are escaped
      // which isn't ideal and breaks the thumbnail generator.
      // So we try the URL with unescaped ampersands first.
      if (url.indexOf("&") > -1) {
        tasks.push(function (next) {
          download(url.split("&").join("&"), headers, next);
        });
      }

      tasks.push(function (next) {
        download(url, headers, next);
      });

      async.tryEach(tasks, function (err, results) {
        // Now we try and download the URL, passing in previously
        // stored headers if any. This module interprets 304
        // responses nicely.
        if (err) return callback(err);

        var path = results[0];

        headers = results[1];

        // We didn't redownload the file since it's
        if (!path && result) return callback(null, result);

        // Something went wrong, if there is no path, no error
        // and no result. So leave before breaking shit.
        if (!path && !result) return callback(missing(url));

        fromPath(path, transform, function (err, result, hash) {
          // The file was downloaded to the temp
          // directory so we remove it now...
          // do this before handling any errors...
          fs.remove(path);

          if (err) return callback(err);

          setURL(url, headers, hash, result, function (err) {
            if (err) throw err;

            callback(err, result);
          });
        });
      });
    });
  }

  function fromPath(path, transform, callback) {
    ensure(path, "string").and(transform, "function").and(callback, "function");

    debug(path, "hashing file");

    HashFile(path, function (err, hash) {
      if (err) return callback(err);

      debug(path, "getting existing result from hash");
      get(hash, function (err, result) {
        // Leave early, please pass hash so that
        // from URL doesn't have to compute it again
        if (err || result) return callback(err, result, hash);

        debug(path, "transforming new file");
        transform(path, function (err, result) {
          if (err) return callback(err);

          // Pass hash so that
          // from URL doesn't have to compute it again
          debug(path, "saving result of new transform");
          set(hash, result, function (err) {
            if (err) throw err;

            callback(err, result, hash);
          });
        });
      });
    });
  }

  function getURL(url, callback) {
    var info = [keys.url.headers(url), keys.url.content(url)];

    client.mget(info, function (err, res) {
      if (err) throw err;

      var headers = null;
      var hash = null;

      try {
        headers = JSON.parse(res[0]);
        hash = res[1];
      } catch (e) {}

      if (hash === null) return callback(err, headers, hash, null);

      get(hash, function (err, result) {
        callback(err, headers, hash, result);
      });
    });
  }

  function get(hash, callback) {
    client.get(keys.content(hash), function (err, stringifiedResult) {
      if (err) throw err;

      var res = null;

      try {
        res = JSON.parse(stringifiedResult);
      } catch (e) {}

      return callback(null, res);
    });
  }

  function setURL(url, headers, hash, result, callback) {
    callback = callback || nothing;

    ensure(url, "string")
      .and(headers, "object")
      .and(hash, "string")
      .and(result, "object")
      .and(callback, "function");

    var urlContentKey = keys.url.content(url);
    var urlHeadersKey = keys.url.headers(url);
    var contentKey = keys.content(hash);

    var stringifiedHeaders = JSON.stringify(headers);
    var stringifiedResult = JSON.stringify(result);

    client
      .multi()
      .sadd(keys.everything, contentKey, urlContentKey, urlHeadersKey)
      .mset(
        urlContentKey,
        hash,
        urlHeadersKey,
        stringifiedHeaders,
        contentKey,
        stringifiedResult
      )
      .exec(callback);
  }

  function set(hash, result, callback) {
    callback = callback || nothing;

    ensure(hash, "string").and(result, "object").and(callback, "function");

    var stringifiedResult = JSON.stringify(result);
    var contentKey = keys.content(hash);

    client
      .multi()
      .sadd(keys.everything, contentKey)
      .set(contentKey, stringifiedResult)
      .exec(callback);
  }

  function flush(callback) {
    client.smembers(keys.everything, function (err, keys) {
      client.del(keys, function () {
        callback();
      });
    });
  }

  return {
    lookup: lookup,
    flush: flush,
  };
}

function nothing(err) {
  if (err) throw err;
}

function missing(src) {
  return new Error("Transformer: URL could not be downloaded: " + clip(src));
}

function clip(src) {
  if (src.length > 50)
    src =
      src.slice(0, 50) + "... (" + (src.length - 50) + " characters removed)";
  return src;
}

module.exports = Transformer;
<|endoftext|>


<commit_before>require("should");

module.exports = function (data) {
    data.should.not.equal(null);
    data.should.instanceOf(Object);

    data.should.have.property('salesContractNo');
    data.salesContractNo.should.instanceOf(String);

    data.should.have.property('deliveryDateCorrection');
    data.deliveryDateCorrection.should.instanceOf(Date);

    data.should.have.property('reason');
    data.name.should.instanceOf(String);
};<commit_msg>Order Status Histories Validator<commit_after>require("should");

module.exports = function (data) {
    data.should.not.equal(null);
    data.should.instanceOf(Object);

    data.should.have.property('salesContractNo');
    data.salesContractNo.should.instanceOf(String);

    data.should.have.property('deliveryDateCorrection');
    data.deliveryDateCorrection.should.instanceOf(Date);

    data.should.have.property('reason');
    data.reason.should.instanceOf(String);
};<|endoftext|>