<commit_before>function Api(config) {
  // create a hash-liked object where all the services handlers are registered
  this.api = Object.create(null);

  // support undefined configuration in constructor
  this.configure(config);
}

Api.prototype = {
  paramsPattern: /:(\w+)/g,

  configure: function (config) {
    this.config = config || {};

    if (!config) {
      return;
    }

    if (this._agent) {
      this._agent.config = config;
    }

    for (var name in config.services) {
      if (!Object.prototype.hasOwnProperty(this, name)) {
        // syntatic sugar: install a service handler available on
        // the api instance with service name
        this.api[name] = Api.defaults.serviceHandler(name).bind(this);
      }
    }
  },

  agent: function() {
    if (!this._agent) {
      throw new Error("no agent configured");
    }
    return this._agent;
  },

  withAgent: function (agent) {
    if (!agent) {
      throw new Error("missing agent");
    }
    this._agent = new Api.defaults.agent(agent);

    if (this.config) {
      this._agent.config = this.config;
    }

    return this;
  },

  service: function(id) {
    return this.config.services ? this.config.services[id] : null;
  },

  url: function(id) {
    var url = this.config.baseUrl;
    var resource = this.service(id) || id;

    // from time being it"s a simple map
    if (resource) {
      var path;

      if (typeof resource === "string") {
        path = resource;
      }

      if (typeof resource === "object" && resource.path !== undefined) {
        path = resource.path;
      }

      if (!path) {
        throw new Error("path is not defined for route $" + id);
      }

      if (path.match(/^https?:\/\//)) {
        url = path;
      }
      else {
        url += path[0] === "/" ? path : "/" + path;
      }
    }

    return url;
  },

  replaceUrl: function(url, params) {
    var tokens = url.match(this.paramsPattern);

    if (!tokens || !tokens.length) {
      return url;
    }

    for (var i = 0, len = tokens.length; i < len; i += 1) {
      var token = tokens[i];
      var name = token.substring(1);
      if (params[name]) {
        url = url.replace(token, params[name]);
      }
    }
    return url;
  },

  buildUrlQuery: function(query) {
    if (!query) {
      return "";
    }

    var queryString;

    if (typeof query === "string") {
      queryString = query;
    } else {
      var queryArgs = [];
      for (var queryArg in query) {
        queryArgs.push(queryArg + "=" + query[queryArg]);
      }
      queryString = queryArgs.join("&");
    }
    return queryString ? "?" + queryString : "";
  },

  buildUrl: function(id, params, query) {
    var url = this.url(id);

    if (params) {
      url = this.replaceUrl(url, params);
    }

    if (query) {
      url += this.buildUrlQuery(query);
    }

    return url;
  },

  request: function(id, data, params, query, method) {
    var service = this.service(id);
    method = method || (service && service.method ? service.method : "get");

    var options = service ? {
      options: service.options,
      headers: service.headers
    } : {}

    return this.agent().buildRequest(method, this.buildUrl(id, params, query), data, options);
  },

  get: function(url, options, data) {
    return this._http('get', url, options, data);
  },

  post: function(url, options, data) {
    return this._http('post', url, options, data);
  },

  put: function(url, options, data) {
    return this._http('put', url, options, data);
  },

  del: function(url, options, data) {
    return this._http('del', url, options, data);
  },

  patch: function(url, options, data) {
    return this._http('patch', url, options, data);
  },

  head: function(url, options, data) {
    return this._http('head', url, options, data);
  },

  _http: function(method, url, options, data) {
    options = options || {};
    options.data = data;
    options.method = method;

    return Api.defaults.serviceHandler(url).call(this, options);
  },

  addHeader: function(name, value) {
    this.agent().addHeader(name, value);
  },

  removeHeader: function(name) {
    this.agent().removeHeader(name);
  },

  middleware: function (name) {
    if (!this.middlewares) {
      return null;
    }
    var found = this.middlewares.filter(function (middleware) {
      return middleware.name === name;
    });

    return found.length > 0 ? found[0] : null;
  },

  status: function (name, handler) {
    if (!this.middleware("status")) {
      this.register("status", Api.defaults.middlewares.status());
    }

    var status = this.middleware("status");

    status.fn.set(name, handler);

    return status;
  },

  register: function (name, fn) {
    if (!this.middlewares) {
      this.middlewares = [];
    }

    this.middlewares.push({
      name: name,
      fn: fn
    });
  },

  _serviceMiddlewares: function (req, service) {
    if (!this.middlewares) {
      return [];
    }

    // Call all the active middlewares for this request and keep a record
    // if it's returning something.
    // Explicitly ignore any middleware returning undefined as it throws with
    // TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
    return this.middlewares.filter(function (middleware) {
      if (!service || !service.use) {
        return true;
      }
      return service.use && service.use[middleware.name] !== false;
    });
  },

  _applyMiddlewares: function (req, sid, stack) {
    var service = this.service(sid);
    var middlewares = this._serviceMiddlewares(req, service);

    // this is the middleware stack that will be called by each active middleware
    // for this request.
    var agent = this.agent();
    var next = function (index, response) {
      return new Promise(function (resolve, reject) {
        stack.push([resolve, reject]);

        if (index === middlewares.length - 1) {
          resolve(agent.handleResponse(req));
        }
      });
    };

    var result = Promise.resolve();
    middlewares.forEach(function (m, i) {
      const res = m.fn(req, next.bind(this, i), service);
      if (res) {
        result = result.then(typeof res === 'function' ? res : function () {
          return res;
        });
      }
    }, this);

    return result;
  }
};

export default Api;
<commit_msg>style(api): switch to var to fix travis build<commit_after>function Api(config) {
  // create a hash-liked object where all the services handlers are registered
  this.api = Object.create(null);

  // support undefined configuration in constructor
  this.configure(config);
}

Api.prototype = {
  paramsPattern: /:(\w+)/g,

  configure: function (config) {
    this.config = config || {};

    if (!config) {
      return;
    }

    if (this._agent) {
      this._agent.config = config;
    }

    for (var name in config.services) {
      if (!Object.prototype.hasOwnProperty(this, name)) {
        // syntatic sugar: install a service handler available on
        // the api instance with service name
        this.api[name] = Api.defaults.serviceHandler(name).bind(this);
      }
    }
  },

  agent: function() {
    if (!this._agent) {
      throw new Error("no agent configured");
    }
    return this._agent;
  },

  withAgent: function (agent) {
    if (!agent) {
      throw new Error("missing agent");
    }
    this._agent = new Api.defaults.agent(agent);

    if (this.config) {
      this._agent.config = this.config;
    }

    return this;
  },

  service: function(id) {
    return this.config.services ? this.config.services[id] : null;
  },

  url: function(id) {
    var url = this.config.baseUrl;
    var resource = this.service(id) || id;

    // from time being it"s a simple map
    if (resource) {
      var path;

      if (typeof resource === "string") {
        path = resource;
      }

      if (typeof resource === "object" && resource.path !== undefined) {
        path = resource.path;
      }

      if (!path) {
        throw new Error("path is not defined for route $" + id);
      }

      if (path.match(/^https?:\/\//)) {
        url = path;
      }
      else {
        url += path[0] === "/" ? path : "/" + path;
      }
    }

    return url;
  },

  replaceUrl: function(url, params) {
    var tokens = url.match(this.paramsPattern);

    if (!tokens || !tokens.length) {
      return url;
    }

    for (var i = 0, len = tokens.length; i < len; i += 1) {
      var token = tokens[i];
      var name = token.substring(1);
      if (params[name]) {
        url = url.replace(token, params[name]);
      }
    }
    return url;
  },

  buildUrlQuery: function(query) {
    if (!query) {
      return "";
    }

    var queryString;

    if (typeof query === "string") {
      queryString = query;
    } else {
      var queryArgs = [];
      for (var queryArg in query) {
        queryArgs.push(queryArg + "=" + query[queryArg]);
      }
      queryString = queryArgs.join("&");
    }
    return queryString ? "?" + queryString : "";
  },

  buildUrl: function(id, params, query) {
    var url = this.url(id);

    if (params) {
      url = this.replaceUrl(url, params);
    }

    if (query) {
      url += this.buildUrlQuery(query);
    }

    return url;
  },

  request: function(id, data, params, query, method) {
    var service = this.service(id);
    method = method || (service && service.method ? service.method : "get");

    var options = service ? {
      options: service.options,
      headers: service.headers
    } : {}

    return this.agent().buildRequest(method, this.buildUrl(id, params, query), data, options);
  },

  get: function(url, options, data) {
    return this._http('get', url, options, data);
  },

  post: function(url, options, data) {
    return this._http('post', url, options, data);
  },

  put: function(url, options, data) {
    return this._http('put', url, options, data);
  },

  del: function(url, options, data) {
    return this._http('del', url, options, data);
  },

  patch: function(url, options, data) {
    return this._http('patch', url, options, data);
  },

  head: function(url, options, data) {
    return this._http('head', url, options, data);
  },

  _http: function(method, url, options, data) {
    options = options || {};
    options.data = data;
    options.method = method;

    return Api.defaults.serviceHandler(url).call(this, options);
  },

  addHeader: function(name, value) {
    this.agent().addHeader(name, value);
  },

  removeHeader: function(name) {
    this.agent().removeHeader(name);
  },

  middleware: function (name) {
    if (!this.middlewares) {
      return null;
    }
    var found = this.middlewares.filter(function (middleware) {
      return middleware.name === name;
    });

    return found.length > 0 ? found[0] : null;
  },

  status: function (name, handler) {
    if (!this.middleware("status")) {
      this.register("status", Api.defaults.middlewares.status());
    }

    var status = this.middleware("status");

    status.fn.set(name, handler);

    return status;
  },

  register: function (name, fn) {
    if (!this.middlewares) {
      this.middlewares = [];
    }

    this.middlewares.push({
      name: name,
      fn: fn
    });
  },

  _serviceMiddlewares: function (req, service) {
    if (!this.middlewares) {
      return [];
    }

    // Call all the active middlewares for this request and keep a record
    // if it's returning something.
    // Explicitly ignore any middleware returning undefined as it throws with
    // TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined
    return this.middlewares.filter(function (middleware) {
      if (!service || !service.use) {
        return true;
      }
      return service.use && service.use[middleware.name] !== false;
    });
  },

  _applyMiddlewares: function (req, sid, stack) {
    var service = this.service(sid);
    var middlewares = this._serviceMiddlewares(req, service);

    // this is the middleware stack that will be called by each active middleware
    // for this request.
    var agent = this.agent();
    var next = function (index, response) {
      return new Promise(function (resolve, reject) {
        stack.push([resolve, reject]);

        if (index === middlewares.length - 1) {
          resolve(agent.handleResponse(req));
        }
      });
    };

    var result = Promise.resolve();
    middlewares.forEach(function (m, i) {
      var res = m.fn(req, next.bind(this, i), service);
      if (res) {
        result = result.then(typeof res === 'function' ? res : function () {
          return res;
        });
      }
    }, this);

    return result;
  }
};

export default Api;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015-2018 PointSource, LLC.
 * MIT Licensed
 */

var path = require('path');
var fs = require('fs');
var debug = require('debug')('swagger');
var async = require('async');
var parser = require('swagger-parser');
var swaggerUtil = require('../lib/swaggerUtil');
var refCompiler = require('../lib/swaggerRefCompiler');
var tv4 = require('tv4');
var _ = require('lodash');
var util = require('util');

var specs = {
    dereferenced: {},
    bundled: {},
    names: []
};

var httpMethods = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch'];

var responseModelValidationLevel;
var polymorphicValidation;
var refCompilation;

exports.discriminatorKeyMap = 'x-bos-generated-disc-map';

exports.init = function (logger, config, callback) {
    var cfg = config.get('swagger');
    // default responseModelValidationLevel to level zero, i.e. off
    responseModelValidationLevel = /warn|error|fail/.test(cfg.validateResponseModels) ?
        cfg.validateResponseModels : 0;
    if (responseModelValidationLevel) {
        logger.info('Response model validation is on and set to level "%s"', responseModelValidationLevel);
    }

    // default polymorphicValidation to 'on'; allow both 'off' and false to turn it off
    polymorphicValidation = /on|warn|off/.test(cfg.polymorphicValidation) ?
        cfg.polymorphicValidation : ((cfg.polymorphicValidation === false) ? 'off' : 'on');
    if (polymorphicValidation !== 'on') {
        logger.info('Polymorphic validation is disabled (%s)', polymorphicValidation);
    }

    refCompilation = typeof cfg.refCompiler === 'object';
    if (refCompilation) {
        logger.info('Ref compilation is enabled (%s), compiling references...', refCompilation);
        refCompiler.compileSpecs(logger, cfg);
    }

    var swaggerDir = null;
    if (isBlueoakProject()) {
        swaggerDir = path.resolve(global.__appDir, '../common/swagger');
    } else {
        swaggerDir = path.resolve(global.__appDir, 'swagger');
    }

    debug('Loading swagger files from %s', swaggerDir);

    var files = [];

    try {
        fs.readdirSync(swaggerDir).forEach(function (fileName) {
            //look for json and yaml
            if (path.extname(fileName) === '.json') {
                files.push(path.resolve(swaggerDir, fileName));
            } else if (path.extname(fileName) === '.yaml') {
                files.push(path.resolve(swaggerDir, fileName));
            }
        });
    } catch (err) {
        //swagger dir probably doesn't exist
        return callback();
    }

    //Loop through all our swagger models
    //For each model, parse it, and automatically hook up the routes to the appropriate handler
    async.eachSeries(files, function parseSwagger(file, swagCallback) {
        var handlerName = path.basename(file); //use the swagger filename as our handler module id
        handlerName = handlerName.substring(0, handlerName.lastIndexOf('.')); //strip extensions

        var derefPromise = parser.validate(file);
        parser.bundle(file)
            .then(function (bundledApi) {
                specs.bundled[handlerName] = bundledApi;
                return derefPromise;
            })
            .then(function (dereferencedApi) {
                specs.dereferenced[handlerName] = dereferencedApi;
                if (polymorphicValidation !== 'off') {
                    preparePathsForPolymorphicValidation(dereferencedApi.paths, responseModelValidationLevel);
                }
                prepareDefinitionsForPolymorphicValidation(dereferencedApi.definitions);
            })
            .then (function () {
                specs.names.push(handlerName);
                return swagCallback();
            })
            .catch(function (error) {
                // don't generate an error if it was a non-Swagger Spec JSON file
                var swagErr = error;
                if (path.extname(file) !== '.yaml') {
                    try {
                        var json = JSON.parse(fs.readFileSync(file, {
                            encoding: 'utf8'
                        }));
                        if (!isSwaggerFile(json)) {
                            logger.info('Skipping non-Swagger JSON file %s', file);
                            swagErr = null;
                        }
                    } catch (err) {
                        logger.error('%s is not valid JSON', file);
                    }
                }
                return swagCallback(swagErr);
            });
    }, function (err) {
        callback(err);
    });

};

exports.getResponseModelValidationLevel = function () {
    return responseModelValidationLevel;
};

exports.isPolymorphicValidationEnabled = function () {
    return polymorphicValidation;
};

exports.getValidHttpMethods = function () {
    return httpMethods;
};

exports.getSpecNames = function () {
    return specs.names;
};

exports.getSimpleSpecs = function () {
    return specs.dereferenced;
};

exports.getPrettySpecs = function () {
    return specs.bundled;
};

exports.addFormat = function (format, validationFunction) {
    tv4.addFormat(format, validationFunction);
};

/**
 * Validate an arbitrary object against a model definition in a given specification
 *
 * @param {Object} object - the object to be validated
 * @param {String|Object} spec - the name of the specification in which the model is defined
 *          or the specification model definition object to use for validation
 * @param {String} model - the name of the model definition to validate against
 *          or the actual model to use
 * @param {Boolean} [skipPolymorphicChecks] - whether to disable polymorphic checks
 *
 * @returns {Object} an object containing the validation result:
 *          .valid is a boolean indicated whether the object validated against the model;
 *          .errors is an array of tv4 validation errors for particular fields;
 *          .polymorphicValidationErrors is an array of tv4 validation errors that only
 *              show with polymorphic validation;
 *
 * @throws {Error} when the model cannot be found
 */
exports.validateObject = function (object, spec, model, skipPolymorphicChecks) {
    var specObject, specName;
    if (typeof spec === 'object') {
        specObject = spec;
        specName = '<inline>';
    } else {
        specName = spec;
        specObject = _.get(specs.dereferenced, spec);
    }
    if (!specObject) {
        throw _createObjectValidationError(
            util.format('Cannot validate object for unknown specification "%s"', specName));
    }

    var modelObject, modelName;
    if (typeof model === 'object') {
        modelObject = model;
        modelName = '<inline>';
    } else {
        modelName = model;
        modelObject = _.get(specObject, ['definitions', modelName].join('.'));
    }
    if (!modelObject) {
        throw _createObjectValidationError(
            util.format('Cannot validate object for unknown model "%s" in specification "%s"', modelName, specName));
    }

    var result = swaggerUtil.validateJSONType(modelObject, object);
    if (!(skipPolymorphicChecks || _.isEmpty(modelObject[exports.discriminatorKeyMap]))) {
        result.polymorphicValidationErrors = swaggerUtil.validateIndividualObjects(
            specObject, modelObject[exports.discriminatorKeyMap], object);
        if (result.polymorphicValidationErrors.length > 0) {
            result.valid = false;
        }
    }

    return result;

    function _createObjectValidationError(message) {
        var error = new Error(message);
        error.name = 'SwaggerObjectValidationError';
        error.specName = specName;
        error.modelName = modelName;
        return error;
    }
};

function preparePathsForPolymorphicValidation(paths, doResponseValidation) {
    var pathKeys = Object.keys(paths);
    pathKeys.forEach(function (path) {
        var methodKeys = Object.keys(paths[path]);
        methodKeys.forEach(function (method) {
            if (httpMethods.indexOf(method) !== -1) {//is this key actually an http method
                if (doResponseValidation) {
                    var responseCodeKeys = Object.keys(paths[path][method].responses);
                    responseCodeKeys.forEach(function (responseCode) {
                        var responseDefinition = paths[path][method].responses[responseCode];
                        _makeSchemaPolymorphic(responseDefinition);
                    });
                }
                if (paths[path][method].parameters) {
                    var requestParamKeys = Object.keys(paths[path][method].parameters);
                    requestParamKeys.forEach(function (param) {
                        var requestParameter = paths[path][method].parameters[param];
                        _makeSchemaPolymorphic(requestParameter);
                    });
                }
            }
        });
    });

    function _makeSchemaPolymorphic(parentObject) {
        if (!parentObject.schema) {
            return;
        }
        _addDiscMapToSchema(parentObject.schema);
        parentObject.schema = _createFlattenedSchema(parentObject.schema);
    }
}

function _addDiscMapToSchema(targetSchema) {
    var discMap = swaggerUtil.getObjectsWithDiscriminator(targetSchema);
    if (targetSchema.allOf) {
        var completeDiscMap = {
            type: 'object'
        };
        completeDiscMap[exports.discriminatorKeyMap] = discMap;
        targetSchema.allOf.push(completeDiscMap);
    } else {
        targetSchema[exports.discriminatorKeyMap] = discMap;
    }
}

function _createFlattenedSchema(sourceSchema) {
    var flattenedSchema;
    if (sourceSchema.type === 'array') {
        flattenedSchema = _.clone(sourceSchema);
        flattenedSchema.items = _createFlattenedSchema(sourceSchema.items);
    } else if (Array.isArray(sourceSchema.allOf)) {
        flattenedSchema = _doFlatMerge({}, sourceSchema);
    } else if (sourceSchema.type === 'object') {
        flattenedSchema = _.cloneDeep(sourceSchema);
    } else {
        flattenedSchema = _.clone(sourceSchema);
    }
    return flattenedSchema;

    function _doFlatMerge(target, source) {
        if (Array.isArray(source.allOf)) {
            source.allOf.forEach(function (duckType) {
                _doFlatMerge(target, duckType);
            });
            return target;
        }

        // we have to handle merging the array `required` on our own
        var reqArr = _.union(target.required, source.required);
        _.merge(target, source);
        target.required = reqArr;
        return target;
    }
}

function prepareDefinitionsForPolymorphicValidation(definitions) {
    var modelNames = Object.keys(definitions);
    modelNames.forEach(function (modelName) {
        var schema = definitions[modelName];
        _addDiscMapToSchema(schema);
        definitions[modelName] = _createFlattenedSchema(schema);
    });
}

//Try to determine if this is supposed to be a swagger file
//For now look for the required "swagger" field, which contains the version
function isSwaggerFile(json) {
    return json.swagger;
}

//There are two possible places for loading swagger.
//If we're part of a broader blueoak client-server project, blueoak is running
//from a 'server' directory, and there's a sibling directory named 'common' which contains the swagger directory.
//Otherwise we just look in the normal swagger folder within the project
function isBlueoakProject() {
    if ((path.basename(global.__appDir) !== 'server')) {
        return false;
    }
    try {
        return fs.statSync(path.resolve(global.__appDir, '../common/swagger')).isDirectory();
    } catch (err) {
        return false;
    }
}<commit_msg>Use lodash.keys to get an empty array on undefined<commit_after>/*
 * Copyright (c) 2015-2018 PointSource, LLC.
 * MIT Licensed
 */

var path = require('path');
var fs = require('fs');
var debug = require('debug')('swagger');
var async = require('async');
var parser = require('swagger-parser');
var swaggerUtil = require('../lib/swaggerUtil');
var refCompiler = require('../lib/swaggerRefCompiler');
var tv4 = require('tv4');
var _ = require('lodash');
var util = require('util');

var specs = {
    dereferenced: {},
    bundled: {},
    names: []
};

var httpMethods = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch'];

var responseModelValidationLevel;
var polymorphicValidation;
var refCompilation;

exports.discriminatorKeyMap = 'x-bos-generated-disc-map';

exports.init = function (logger, config, callback) {
    var cfg = config.get('swagger');
    // default responseModelValidationLevel to level zero, i.e. off
    responseModelValidationLevel = /warn|error|fail/.test(cfg.validateResponseModels) ?
        cfg.validateResponseModels : 0;
    if (responseModelValidationLevel) {
        logger.info('Response model validation is on and set to level "%s"', responseModelValidationLevel);
    }

    // default polymorphicValidation to 'on'; allow both 'off' and false to turn it off
    polymorphicValidation = /on|warn|off/.test(cfg.polymorphicValidation) ?
        cfg.polymorphicValidation : ((cfg.polymorphicValidation === false) ? 'off' : 'on');
    if (polymorphicValidation !== 'on') {
        logger.info('Polymorphic validation is disabled (%s)', polymorphicValidation);
    }

    refCompilation = typeof cfg.refCompiler === 'object';
    if (refCompilation) {
        logger.info('Ref compilation is enabled (%s), compiling references...', refCompilation);
        refCompiler.compileSpecs(logger, cfg);
    }

    var swaggerDir = null;
    if (isBlueoakProject()) {
        swaggerDir = path.resolve(global.__appDir, '../common/swagger');
    } else {
        swaggerDir = path.resolve(global.__appDir, 'swagger');
    }

    debug('Loading swagger files from %s', swaggerDir);

    var files = [];

    try {
        fs.readdirSync(swaggerDir).forEach(function (fileName) {
            //look for json and yaml
            if (path.extname(fileName) === '.json') {
                files.push(path.resolve(swaggerDir, fileName));
            } else if (path.extname(fileName) === '.yaml') {
                files.push(path.resolve(swaggerDir, fileName));
            }
        });
    } catch (err) {
        //swagger dir probably doesn't exist
        return callback();
    }

    //Loop through all our swagger models
    //For each model, parse it, and automatically hook up the routes to the appropriate handler
    async.eachSeries(files, function parseSwagger(file, swagCallback) {
        var handlerName = path.basename(file); //use the swagger filename as our handler module id
        handlerName = handlerName.substring(0, handlerName.lastIndexOf('.')); //strip extensions

        var derefPromise = parser.validate(file);
        parser.bundle(file)
            .then(function (bundledApi) {
                specs.bundled[handlerName] = bundledApi;
                return derefPromise;
            })
            .then(function (dereferencedApi) {
                specs.dereferenced[handlerName] = dereferencedApi;
                if (polymorphicValidation !== 'off') {
                    preparePathsForPolymorphicValidation(dereferencedApi.paths, responseModelValidationLevel);
                }
                prepareDefinitionsForPolymorphicValidation(dereferencedApi.definitions);
            })
            .then (function () {
                specs.names.push(handlerName);
                return swagCallback();
            })
            .catch(function (error) {
                // don't generate an error if it was a non-Swagger Spec JSON file
                var swagErr = error;
                if (path.extname(file) !== '.yaml') {
                    try {
                        var json = JSON.parse(fs.readFileSync(file, {
                            encoding: 'utf8'
                        }));
                        if (!isSwaggerFile(json)) {
                            logger.info('Skipping non-Swagger JSON file %s', file);
                            swagErr = null;
                        }
                    } catch (err) {
                        logger.error('%s is not valid JSON', file);
                    }
                }
                return swagCallback(swagErr);
            });
    }, function (err) {
        callback(err);
    });

};

exports.getResponseModelValidationLevel = function () {
    return responseModelValidationLevel;
};

exports.isPolymorphicValidationEnabled = function () {
    return polymorphicValidation;
};

exports.getValidHttpMethods = function () {
    return httpMethods;
};

exports.getSpecNames = function () {
    return specs.names;
};

exports.getSimpleSpecs = function () {
    return specs.dereferenced;
};

exports.getPrettySpecs = function () {
    return specs.bundled;
};

exports.addFormat = function (format, validationFunction) {
    tv4.addFormat(format, validationFunction);
};

/**
 * Validate an arbitrary object against a model definition in a given specification
 *
 * @param {Object} object - the object to be validated
 * @param {String|Object} spec - the name of the specification in which the model is defined
 *          or the specification model definition object to use for validation
 * @param {String} model - the name of the model definition to validate against
 *          or the actual model to use
 * @param {Boolean} [skipPolymorphicChecks] - whether to disable polymorphic checks
 *
 * @returns {Object} an object containing the validation result:
 *          .valid is a boolean indicated whether the object validated against the model;
 *          .errors is an array of tv4 validation errors for particular fields;
 *          .polymorphicValidationErrors is an array of tv4 validation errors that only
 *              show with polymorphic validation;
 *
 * @throws {Error} when the model cannot be found
 */
exports.validateObject = function (object, spec, model, skipPolymorphicChecks) {
    var specObject, specName;
    if (typeof spec === 'object') {
        specObject = spec;
        specName = '<inline>';
    } else {
        specName = spec;
        specObject = _.get(specs.dereferenced, spec);
    }
    if (!specObject) {
        throw _createObjectValidationError(
            util.format('Cannot validate object for unknown specification "%s"', specName));
    }

    var modelObject, modelName;
    if (typeof model === 'object') {
        modelObject = model;
        modelName = '<inline>';
    } else {
        modelName = model;
        modelObject = _.get(specObject, ['definitions', modelName].join('.'));
    }
    if (!modelObject) {
        throw _createObjectValidationError(
            util.format('Cannot validate object for unknown model "%s" in specification "%s"', modelName, specName));
    }

    var result = swaggerUtil.validateJSONType(modelObject, object);
    if (!(skipPolymorphicChecks || _.isEmpty(modelObject[exports.discriminatorKeyMap]))) {
        result.polymorphicValidationErrors = swaggerUtil.validateIndividualObjects(
            specObject, modelObject[exports.discriminatorKeyMap], object);
        if (result.polymorphicValidationErrors.length > 0) {
            result.valid = false;
        }
    }

    return result;

    function _createObjectValidationError(message) {
        var error = new Error(message);
        error.name = 'SwaggerObjectValidationError';
        error.specName = specName;
        error.modelName = modelName;
        return error;
    }
};

function preparePathsForPolymorphicValidation(paths, doResponseValidation) {
    var pathKeys = _.keys(paths);
    pathKeys.forEach(function (path) {
        var methodKeys = _.keys(paths[path]);
        methodKeys.forEach(function (method) {
            if (httpMethods.indexOf(method) !== -1) {//is this key actually an http method
                if (doResponseValidation) {
                    var responseCodeKeys = _.keys(paths[path][method].responses);
                    responseCodeKeys.forEach(function (responseCode) {
                        var responseDefinition = paths[path][method].responses[responseCode];
                        _makeSchemaPolymorphic(responseDefinition);
                    });
                }
                if (paths[path][method].parameters) {
                    var requestParamKeys = _.keys(paths[path][method].parameters);
                    requestParamKeys.forEach(function (param) {
                        var requestParameter = paths[path][method].parameters[param];
                        _makeSchemaPolymorphic(requestParameter);
                    });
                }
            }
        });
    });

    function _makeSchemaPolymorphic(parentObject) {
        if (!parentObject.schema) {
            return;
        }
        _addDiscMapToSchema(parentObject.schema);
        parentObject.schema = _createFlattenedSchema(parentObject.schema);
    }
}

function _addDiscMapToSchema(targetSchema) {
    var discMap = swaggerUtil.getObjectsWithDiscriminator(targetSchema);
    if (targetSchema.allOf) {
        var completeDiscMap = {
            type: 'object'
        };
        completeDiscMap[exports.discriminatorKeyMap] = discMap;
        targetSchema.allOf.push(completeDiscMap);
    } else {
        targetSchema[exports.discriminatorKeyMap] = discMap;
    }
}

function _createFlattenedSchema(sourceSchema) {
    var flattenedSchema;
    if (sourceSchema.type === 'array') {
        flattenedSchema = _.clone(sourceSchema);
        flattenedSchema.items = _createFlattenedSchema(sourceSchema.items);
    } else if (Array.isArray(sourceSchema.allOf)) {
        flattenedSchema = _doFlatMerge({}, sourceSchema);
    } else if (sourceSchema.type === 'object') {
        flattenedSchema = _.cloneDeep(sourceSchema);
    } else {
        flattenedSchema = _.clone(sourceSchema);
    }
    return flattenedSchema;

    function _doFlatMerge(target, source) {
        if (Array.isArray(source.allOf)) {
            source.allOf.forEach(function (duckType) {
                _doFlatMerge(target, duckType);
            });
            return target;
        }

        // we have to handle merging the array `required` on our own
        var reqArr = _.union(target.required, source.required);
        _.merge(target, source);
        target.required = reqArr;
        return target;
    }
}

function prepareDefinitionsForPolymorphicValidation(definitions) {
    var modelNames = _.keys(definitions);
    modelNames.forEach(function (modelName) {
        var schema = definitions[modelName];
        _addDiscMapToSchema(schema);
        definitions[modelName] = _createFlattenedSchema(schema);
    });
}

//Try to determine if this is supposed to be a swagger file
//For now look for the required "swagger" field, which contains the version
function isSwaggerFile(json) {
    return json.swagger;
}

//There are two possible places for loading swagger.
//If we're part of a broader blueoak client-server project, blueoak is running
//from a 'server' directory, and there's a sibling directory named 'common' which contains the swagger directory.
//Otherwise we just look in the normal swagger folder within the project
function isBlueoakProject() {
    if ((path.basename(global.__appDir) !== 'server')) {
        return false;
    }
    try {
        return fs.statSync(path.resolve(global.__appDir, '../common/swagger')).isDirectory();
    } catch (err) {
        return false;
    }
}<|endoftext|>


<commit_before>// Copyright (C) 2016 Goom Inc. All rights reserved.

import React, { PropTypes } from 'react';
import { Link } from 'react-router';

import orderUtil from 'commons/utils/orderUtil';
import roleUtil from 'commons/utils/roleUtil';
import i18n from 'commons/utils/i18n';
import { constants } from 'commons/utils/constants';

const _ = require('lodash');

export default React.createClass({
  propTypes: {
    auth: PropTypes.object.isRequired,
    cart: PropTypes.object.isRequired,
    categories: PropTypes.object,
    activeCategory: PropTypes.object,
    showSearchDropdown: PropTypes.bool,
    toggleSearchDropdown: PropTypes.func.isRequired,
    selectSearchDropdown: PropTypes.func.isRequired,
    handleLogout: PropTypes.func.isRequired,
    handleSearch: PropTypes.func.isRequired,
    changeLocale: PropTypes.func.isRequired,
    changeCurrency: PropTypes.func.isRequired,
    params: PropTypes.object,
  },
  contextTypes: {
    activeLocale: PropTypes.string,
    activeCurrency: PropTypes.string,
    isLogin: PropTypes.func,
  },
  componentWillReceiveProps(nextProps) {
    if (nextProps.params.query !== this.props.params.query) {
      this.refs.searchQuery.value = nextProps.params.query || '';
    }
  },
  render() {
    const { auth, handleLogout, handleSearch, cart, categories, changeLocale, changeCurrency } = this.props;
    const { toggleSearchDropdown, selectSearchDropdown, showSearchDropdown, activeCategory, params } = this.props;
    const { activeLocale, activeCurrency } = this.context;
    const cartCount = orderUtil.getProductVariantsFromCart(cart).length;
    const renderSearchDropdownItems = () => {
      const items = _.get(categories, 'tree.children') || [];
      return items.map((item, index) => {
        let className = 'search-dropdown-item';
        if (activeCategory && activeCategory.id === item.id) {
          className += ' active';
        }
        return (

 selectSearchDropdown(item)} key={index} className={className}>
            {item.name[activeLocale]}

        );
      });
    };
    const renderSearchDropdown = () => {
      if (!showSearchDropdown) {
        return (

);
      }
      let allCategoriesClassName = 'search-dropdown-item';
      if (!activeCategory) {
        allCategoriesClassName += ' active';
      }
      return (

 $('.helper-menu-item').removeClass('open')}>

 selectSearchDropdown(null)} className={allCategoriesClassName}>
            {i18n.get('word.allCategories')}

          {renderSearchDropdownItems()}

      );
    };
    const locales = {
      ko: { img: `${constants.resourceRoot}/header/flag-kor.png`, name: '한국어' },
      en: { img: `${constants.resourceRoot}/header/flag-eng.png`, name: 'ENGLISH' },
      'zh-cn': { img: `${constants.resourceRoot}/header/flag-chi.png`, name: '简体' },
      'zh-tw': { img: `${constants.resourceRoot}/header/flag-tai.png`, name: '繁體' },
    };
    const renderLocales = () => (

        {Object.keys(locales).map((key) => (
          <div key={key} className={`dropdown-menu ${key === activeLocale ? 'active' : ''}`}
            onClick={() => {
              changeLocale(key);
              $('.left-menu-item').removeClass('open');
            }}
          > {locales[key].name}

        ))}

    );
    const currencies = constants.currencies;
    const renderCurrencies = () => {
      return (

          {currencies.map((obj) => (
            <div key={obj.name} className={`dropdown-menu ${obj.name === activeCurrency ? 'active' : ''}`}
              onClick={() => {
                changeCurrency(obj.name);
                $('.left-menu-item').removeClass('open');
              }}
            >
               {obj.name}

          ))}

      );
    };
    const getLocaleImg = () => {
      return locales[activeLocale].img;
    };
    const getCurrencyImg = () => {
      for (let i = 0; i < currencies.length; i++) {
        if (currencies[i].name === activeCurrency) {
          return currencies[i].img;
        }
      }
      return '';
    };
    const renderMypageMenus = () => {
      const menus = [
        { link: '/mypage/my_orders', text: i18n.get('pcMain.myMenu.myOrders') },
        { link: '/mypage/user_info', text: i18n.get('pcMain.myMenu.userInfo') },
        { link: '/mypage/reorder', text: i18n.get('word.reorder') },
      ];
      const renderMenu = (menu) => (

 {
            $('.helper-menu-item').removeClass('open');
          }}
        >
          <Link to={menu.link}>{menu.text}</Link>

      );
      return (

          {menus.map(renderMenu)}

      );
    };

    const handleSearchSubmit = (e) => {
      e.preventDefault();
      handleSearch(this.refs.searchQuery.value, activeCategory && activeCategory.id);
    };

    const brandId = roleUtil.getBrandIdIfSeller(auth);
    const renderTopHelperRightMenus = () => {
      if (brandId) {
        // seller does not need my page
        return (

            {i18n.get('word.logout')}

        );
      }
      if (this.context.isLogin()) {
        const getName = (email) => {
          const idx = email.indexOf('@');
          if (idx > 0) {
            return email.substring(0, idx);
          }
          return email;
        };
        return [

            <Link to="/mypage">{i18n.get('word.hi')} {getName(auth.email)}</Link>

,

 $(e.target).addClass('open')}
            onMouseLeave={(e) => $(e.target).closest('.helper-menu-item').removeClass('open')}
          >
            {i18n.get('word.myPage')}
            {renderMypageMenus()}

,

            {i18n.get('word.logout')}

,

            <Link to="/service/info/customer_center">{i18n.get('word.customerCenter')}</Link>

,
        ];
      }
      return [
        <Link key="app-header-signin" to="/accounts/signin">

{i18n.get('word.login')}

        </Link>,
        <Link key="app-header-signup" to="/accounts/signup">

{i18n.get('word.register')}

        </Link>,
        <Link key="app-header-customer2" to="/service/info/customer_center">

{i18n.get('word.customerCenter')}

        </Link>,
      ];
    };

    const headerRightMenuItemClassName = `menu-item ${activeLocale}`;
    const leftMenuItemClassName = 'left-menu-item';

    const renderMyMenus = () => {
      if (brandId) {
        return (
          <Link to={`/brands/${brandId}`}>

상품 조회

          </Link>
        );
      }
      return [
        <Link key="mypage_wish_list" to="/mypage/wish_list">

{i18n.get('word.wishList')}

        </Link>,
        <Link key="mypage_favorite_brands" to="/mypage/favorite_brands">

{i18n.get('word.favoriteBrand')}

        </Link>,
        <Link key="mypage_cart" to="/cart">

            {i18n.get('word.cart')}
            <img src={`${constants.resourceRoot}/header/ico_cart.png`} />
            {cartCount}

        </Link>,
      ];
    };

    return (

 $(e.target).addClass('open')}
                onMouseLeave={(e) => $(e.target).closest(`.${leftMenuItemClassName}`).removeClass('open')}
              >
                 {i18n.get('word.language')}
                {renderLocales()}

 $(e.target).addClass('open')}
                onMouseLeave={(e) => $(e.target).closest(`.${leftMenuItemClassName}`).removeClass('open')}
              >
                 {i18n.get('word.currency')}
                {renderCurrencies()}

              {renderTopHelperRightMenus()}

            <Link className="header-item" to="/">

            </Link>

              <form onSubmit={handleSearchSubmit}>

                {activeCategory ? activeCategory.name[activeLocale] : i18n.get('word.allCategories')}
                {renderSearchDropdown()}

              <input ref="searchQuery" placeholder={i18n.get('pcMain.search.placeHolder')}
                defaultValue={params.query || ''}
              />
              <button className="header-search-button" type="submit"></button>
              </form>

              {renderMyMenus()}

    );
  },
});
<commit_msg>Case 102<commit_after>// Copyright (C) 2016 Goom Inc. All rights reserved.

import React, { PropTypes } from 'react';
import { Link } from 'react-router';

import orderUtil from 'commons/utils/orderUtil';
import roleUtil from 'commons/utils/roleUtil';
import i18n from 'commons/utils/i18n';
import { constants } from 'commons/utils/constants';

const _ = require('lodash');

export default React.createClass({
  propTypes: {
    auth: PropTypes.object.isRequired,
    cart: PropTypes.object.isRequired,
    categories: PropTypes.object,
    activeCategory: PropTypes.object,
    showSearchDropdown: PropTypes.bool,
    toggleSearchDropdown: PropTypes.func.isRequired,
    selectSearchDropdown: PropTypes.func.isRequired,
    handleLogout: PropTypes.func.isRequired,
    handleSearch: PropTypes.func.isRequired,
    changeLocale: PropTypes.func.isRequired,
    changeCurrency: PropTypes.func.isRequired,
    params: PropTypes.object,
  },
  contextTypes: {
    activeLocale: PropTypes.string,
    activeCurrency: PropTypes.string,
    isLogin: PropTypes.func,
  },
  componentWillReceiveProps(nextProps) {
    if (nextProps.params.query !== this.props.params.query) {
      this.refs.searchQuery.value = nextProps.params.query || '';
    }
  },
  render() {
    const { auth, handleLogout, handleSearch, cart, categories, changeLocale, changeCurrency } = this.props;
    const { toggleSearchDropdown, selectSearchDropdown, showSearchDropdown, activeCategory, params } = this.props;
    const { activeLocale, activeCurrency } = this.context;
    const cartCount = orderUtil.getProductVariantsFromCart(cart).length;
    const renderSearchDropdownItems = () => {
      const items = _.get(categories, 'tree.children') || [];
      return items.map((item, index) => {
        let className = 'search-dropdown-item';
        if (activeCategory && activeCategory.id === item.id) {
          className += ' active';
        }
        return (

 selectSearchDropdown(item)} key={index} className={className}>
            {item.name[activeLocale]}

        );
      });
    };
    const renderSearchDropdown = () => {
      if (!showSearchDropdown) {
        return (

);
      }
      let allCategoriesClassName = 'search-dropdown-item';
      if (!activeCategory) {
        allCategoriesClassName += ' active';
      }
      return (

 $('.helper-menu-item').removeClass('open')}>

 selectSearchDropdown(null)} className={allCategoriesClassName}>
            {i18n.get('word.allCategories')}

          {renderSearchDropdownItems()}

      );
    };
    const locales = {
      ko: { img: `${constants.resourceRoot}/header/flag-kor.png`, name: '한국어' },
      en: { img: `${constants.resourceRoot}/header/flag-eng.png`, name: 'ENGLISH' },
      'zh-cn': { img: `${constants.resourceRoot}/header/flag-chi.png`, name: '简体' },
      'zh-tw': { img: `${constants.resourceRoot}/header/flag-tai.png`, name: '繁體' },
    };
    const renderLocales = () => (

        {Object.keys(locales).map((key) => (
          <div key={key} className={`dropdown-menu ${key === activeLocale ? 'active' : ''}`}
            onClick={() => {
              changeLocale(key);
              $('.left-menu-item').removeClass('open');
            }}
          > {locales[key].name}

        ))}

    );
    const currencies = constants.currencies;
    const renderCurrencies = () => {
      return (

          {currencies.map((obj) => (
            <div key={obj.name} className={`dropdown-menu ${obj.name === activeCurrency ? 'active' : ''}`}
              onClick={() => {
                changeCurrency(obj.name);
                $('.left-menu-item').removeClass('open');
              }}
            >
               {obj.name}

          ))}

      );
    };
    const getLocaleImg = () => {
      return locales[activeLocale].img;
    };
    const getCurrencyImg = () => {
      for (let i = 0; i < currencies.length; i++) {
        if (currencies[i].name === activeCurrency) {
          return currencies[i].img;
        }
      }
      return '';
    };
    const renderMypageMenus = () => {
      const menus = [
        { link: '/mypage/my_orders', text: i18n.get('pcMain.myMenu.myOrders') },
        { link: '/mypage/user_info', text: i18n.get('pcMain.myMenu.userInfo') },
      ];
      if (roleUtil.hasRole(auth, ['bigBuyer', 'admin'])) {
        menus.push({ link: '/mypage/reorder', text: i18n.get('word.reorder') });
      }
      const renderMenu = (menu) => (

 {
            $('.helper-menu-item').removeClass('open');
          }}
        >
          <Link to={menu.link}>{menu.text}</Link>

      );
      return (

          {menus.map(renderMenu)}

      );
    };

    const handleSearchSubmit = (e) => {
      e.preventDefault();
      handleSearch(this.refs.searchQuery.value, activeCategory && activeCategory.id);
    };

    const brandId = roleUtil.getBrandIdIfSeller(auth);
    const renderTopHelperRightMenus = () => {
      if (brandId) {
        // seller does not need my page
        return (

            {i18n.get('word.logout')}

        );
      }
      if (this.context.isLogin()) {
        const getName = (email) => {
          const idx = email.indexOf('@');
          if (idx > 0) {
            return email.substring(0, idx);
          }
          return email;
        };
        return [

            <Link to="/mypage">{i18n.get('word.hi')} {getName(auth.email)}</Link>

,

 $(e.target).addClass('open')}
            onMouseLeave={(e) => $(e.target).closest('.helper-menu-item').removeClass('open')}
          >
            {i18n.get('word.myPage')}
            {renderMypageMenus()}

,

            {i18n.get('word.logout')}

,

            <Link to="/service/info/customer_center">{i18n.get('word.customerCenter')}</Link>

,
        ];
      }
      return [
        <Link key="app-header-signin" to="/accounts/signin">

{i18n.get('word.login')}

        </Link>,
        <Link key="app-header-signup" to="/accounts/signup">

{i18n.get('word.register')}

        </Link>,
        <Link key="app-header-customer2" to="/service/info/customer_center">

{i18n.get('word.customerCenter')}

        </Link>,
      ];
    };

    const headerRightMenuItemClassName = `menu-item ${activeLocale}`;
    const leftMenuItemClassName = 'left-menu-item';

    const renderMyMenus = () => {
      if (brandId) {
        return (
          <Link to={`/brands/${brandId}`}>

상품 조회

          </Link>
        );
      }
      return [
        <Link key="mypage_wish_list" to="/mypage/wish_list">

{i18n.get('word.wishList')}

        </Link>,
        <Link key="mypage_favorite_brands" to="/mypage/favorite_brands">

{i18n.get('word.favoriteBrand')}

        </Link>,
        <Link key="mypage_cart" to="/cart">

            {i18n.get('word.cart')}
            <img src={`${constants.resourceRoot}/header/ico_cart.png`} />
            {cartCount}

        </Link>,
      ];
    };

    return (

 $(e.target).addClass('open')}
                onMouseLeave={(e) => $(e.target).closest(`.${leftMenuItemClassName}`).removeClass('open')}
              >
                 {i18n.get('word.language')}
                {renderLocales()}

 $(e.target).addClass('open')}
                onMouseLeave={(e) => $(e.target).closest(`.${leftMenuItemClassName}`).removeClass('open')}
              >
                 {i18n.get('word.currency')}
                {renderCurrencies()}

              {renderTopHelperRightMenus()}

            <Link className="header-item" to="/">

            </Link>

              <form onSubmit={handleSearchSubmit}>

                {activeCategory ? activeCategory.name[activeLocale] : i18n.get('word.allCategories')}
                {renderSearchDropdown()}

              <input ref="searchQuery" placeholder={i18n.get('pcMain.search.placeHolder')}
                defaultValue={params.query || ''}
              />
              <button className="header-search-button" type="submit"></button>
              </form>

              {renderMyMenus()}

    );
  },
});
<|endoftext|>


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

	angular.module('app.components')
	  .factory('asset', asset);

    asset.$inject = ['assetsAPI', '$window', 'timeUtils', '$filter', '$q'];
	  function asset(assetsAPI, $window, timeUtils, $filter, $q) {

      var worldMarkers, assets, assetsPrevious, worldClusters;

      initialize();

	  	var service = {
        getAllEntities: getAllEntities,
        setAllEntities: setAllEntities,
        getAllClusters: getAllClusters,
        setAllClusters: setAllClusters,
				getMetadata: getMetadata,
        getAsset: getAsset,
        createAsset: createAsset,
        updateAsset: updateAsset,
        getWorldMarkers: getWorldMarkers,
        setWorldMarkers: setWorldMarkers,
				getClusterGeoJSON: getClusterGeoJSON,
        getGeoJSON: getGeoJSON,
        getGeoJSONSite: getGeoJSONSite
	  	};

	  	return service;

	  	//////////////////////////

      function initialize() {
        if(areMarkersOld()) {
          removeMarkers();
        }
      }

      function setAllEntities(data) {
        var obj = {
          timestamp: new Date(),
          data: data
        };
        removeEntitiesMarkers();
        $window.localStorage.setItem('organicity.assets', JSON.stringify(obj));
        assets = obj.data;
				return assets;
      }

      function setAllClusters(data) {
        worldClusters = data;
      }

      function getAllClusters() {
        return (worldClusters) ? worldClusters : false;
      }

      function setPrevAllEntities() {
        assetsPrevious = assets;
      }

      function getPrevAllEntities() {
        var deferred = $q.defer();
        deferred.resolve(assetsPrevious);
        return deferred.promise;
      }

      function getAllEntities() {
          console.log('Data expired: Refreshing assets');
          return assetsAPI.one('assets').get({'page': '1', 'per': '100'});
      }

			function getMetadata(query) {
				return assetsAPI.one('assets/metadata/search').get({'page': '1', 'per': '20', 'query': query});
			}

			function getGeoJSONSite(site) {
				var endpoint = 'assets/sites/' + site + '/geo';
        return assetsAPI.one(endpoint).get();
			}

			function getGeoJSON(params) {
				var endpoint = 'assets/geo/search';
				return  assetsAPI.one(endpoint).get(params);
			}

      function getClusterGeoJSON() {

            /*

            This implementation is completly temporary to support first
            Open Call while the cluster service on the Asset Discovery Backend
            is finalized.

            */

					var devices = [];

					var locations = [
            ['43.45487000', '-3.81289000', 'Santander'],  	// Santander
            ['51.50722200', '-0.12750000', 'London'],		// London
            ['56.15720000', '10.21070000', 'Aarhus'], 		// Aarhus
            ['38.25000000', '21.73333300', 'Patras'], 		// Patras
            ['55.93270000', '-2.98140000', 'Edinburgh'],	// Edinburgh
            ['50.87947200', '4.701072000', 'Leuven'],		// Leuven
            ['-9.13346700', '38.71400600', 'Lisbon'],		// Lisbon
            ['19.83354900', '45.26713600', 'NoviSad']		// Novisad
					];

					for(var i = 0; i < 4; i++) {
						var endpoint = 'assets/geo/zoom/1';
						var params = {lat: locations[i][0],  long: locations[i][1]};

				    var devs = assetsAPI.one(endpoint).get(params);
						devices.push(devs);
					}

					var data = $q.all(devices).then(function(devices) {
						return '{ "type": "FeatureCollection", "properties": { "name": "urn:oc:assettype:clusters"}, "features": [' + getGeoDevices(devices) + ']}';
					});
					return data;
      }

			function getGeoDevices(devices) {
				return devices.map(getGeoData);
			}

			function getGeoData(elem) {
				return '{ "type": "' + elem.type + '", "geometry":' + JSON.stringify(elem.geometry) + ', "properties":' + JSON.stringify(elem.properties) + '}';
			}

      function getEntitiesMarkers(location) {
        var parameter = '';
        parameter += location.lat + ',' + location.lng;
        return assetsAPI.all('assets').getList({'page': '1', 'per': '100'});
      }

      function getAsset(id) {
				var endpoint = 'assets/' + id;
        return assetsAPI.one(endpoint).get({});
      }

      function createAsset(data) {
        return assetsAPI.all('assets').post(data);
      }

      function updateAsset(id, data) {
        return assetsAPI.one('assets', id).patch(data);
      }

      function getWorldMarkers() {
        console.log('Data is cached: Markers are less than 60sec old.');
        return worldMarkers || ($window.localStorage.getItem('organicity.markers') && JSON.parse($window.localStorage.getItem('organicity.markers') ).data);
      }

      function setWorldMarkers(data) {
        var obj = {
          timestamp: new Date(),
          data: data
        };

        $window.localStorage.setItem('organicity.markers', JSON.stringify(obj) );
        worldMarkers = obj.data;
      }

      function getEntitiesTimeStamp() {
        return ($window.localStorage.getItem('organicity.assets') && JSON.parse($window.localStorage.getItem('organicity.assets') ).timestamp);
      }

      function areEntitiesMarkersOld() {
        var markersDate = getEntitiesTimeStamp();
        return !timeUtils.isWithin(60, 'seconds', markersDate);
      }

      function removeEntitiesMarkers() {
        $window.localStorage.removeItem('organicity.assets');
      }

      function getTimeStamp() {
        return ($window.localStorage.getItem('organicity.markers') && JSON.parse($window.localStorage.getItem('organicity.markers') ).timestamp);
      }

      function areMarkersOld() {
        var markersDate = getTimeStamp();
        return !timeUtils.isWithin(60, 'seconds', markersDate);
      }

      function removeMarkers() {
        $window.localStorage.removeItem('organicity.markers');
      }
	  }
})();
<commit_msg>Update asset.service.js<commit_after>(function() {
	'use strict';

	angular.module('app.components')
	  .factory('asset', asset);

    asset.$inject = ['assetsAPI', '$window', 'timeUtils', '$filter', '$q'];
	  function asset(assetsAPI, $window, timeUtils, $filter, $q) {

      var worldMarkers, assets, assetsPrevious, worldClusters;

      initialize();

	  	var service = {
        getAllEntities: getAllEntities,
        setAllEntities: setAllEntities,
        getAllClusters: getAllClusters,
        setAllClusters: setAllClusters,
				getMetadata: getMetadata,
        getAsset: getAsset,
        createAsset: createAsset,
        updateAsset: updateAsset,
        getWorldMarkers: getWorldMarkers,
        setWorldMarkers: setWorldMarkers,
				getClusterGeoJSON: getClusterGeoJSON,
        getGeoJSON: getGeoJSON,
        getGeoJSONSite: getGeoJSONSite
	  	};

	  	return service;

	  	//////////////////////////

      function initialize() {
        if(areMarkersOld()) {
          removeMarkers();
        }
      }

      function setAllEntities(data) {
        var obj = {
          timestamp: new Date(),
          data: data
        };
        removeEntitiesMarkers();
        $window.localStorage.setItem('organicity.assets', JSON.stringify(obj));
        assets = obj.data;
				return assets;
      }

      function setAllClusters(data) {
        worldClusters = data;
      }

      function getAllClusters() {
        return (worldClusters) ? worldClusters : false;
      }

      function setPrevAllEntities() {
        assetsPrevious = assets;
      }

      function getPrevAllEntities() {
        var deferred = $q.defer();
        deferred.resolve(assetsPrevious);
        return deferred.promise;
      }

      function getAllEntities() {
          console.log('Data expired: Refreshing assets');
          return assetsAPI.one('assets').get({'page': '1', 'per': '100'});
      }

			function getMetadata(query) {
				return assetsAPI.one('assets/metadata/search').get({'page': '1', 'per': '20', 'query': query});
			}

			function getGeoJSONSite(site) {
				var endpoint = 'assets/sites/' + site + '/geo';
        return assetsAPI.one(endpoint).get();
			}

			function getGeoJSON(params) {
				var endpoint = 'assets/geo/search';
				return  assetsAPI.one(endpoint).get(params);
			}

      function getClusterGeoJSON() {

            /*

            This implementation is completly temporary to support first
            Open Call while the cluster service on the Asset Discovery Backend
            is finalized.

            */

					var devices = [];

					var locations = [
            ['43.45487000', '-3.81289000', 'Santander'],  // Santander
            ['51.50722200', '-0.12750000', 'London'],     // London
            ['56.15720000', '10.21070000', 'Aarhus'],     // Aarhus
            ['38.25000000', '21.73333300', 'Patras'],     // Patras
            ['55.93270000', '-2.98140000', 'Edinburgh'],  // Edinburgh
            ['50.87947200', '4.701072000', 'Leuven'],     // Leuven
            ['-9.13346700', '38.71400600', 'Lisbon'],     // Lisbon
            ['19.83354900', '45.26713600', 'NoviSad'],    // Novisad
            ['15.110658', '46.362274', 'Velenje']         // Velenje
					];

					for(var i = 0; i < 4; i++) {
						var endpoint = 'assets/geo/zoom/1';
						var params = {lat: locations[i][0],  long: locations[i][1]};

				    var devs = assetsAPI.one(endpoint).get(params);
						devices.push(devs);
					}

					var data = $q.all(devices).then(function(devices) {
						return '{ "type": "FeatureCollection", "properties": { "name": "urn:oc:assettype:clusters"}, "features": [' + getGeoDevices(devices) + ']}';
					});
					return data;
      }

			function getGeoDevices(devices) {
				return devices.map(getGeoData);
			}

			function getGeoData(elem) {
				return '{ "type": "' + elem.type + '", "geometry":' + JSON.stringify(elem.geometry) + ', "properties":' + JSON.stringify(elem.properties) + '}';
			}

      function getEntitiesMarkers(location) {
        var parameter = '';
        parameter += location.lat + ',' + location.lng;
        return assetsAPI.all('assets').getList({'page': '1', 'per': '100'});
      }

      function getAsset(id) {
				var endpoint = 'assets/' + id;
        return assetsAPI.one(endpoint).get({});
      }

      function createAsset(data) {
        return assetsAPI.all('assets').post(data);
      }

      function updateAsset(id, data) {
        return assetsAPI.one('assets', id).patch(data);
      }

      function getWorldMarkers() {
        console.log('Data is cached: Markers are less than 60sec old.');
        return worldMarkers || ($window.localStorage.getItem('organicity.markers') && JSON.parse($window.localStorage.getItem('organicity.markers') ).data);
      }

      function setWorldMarkers(data) {
        var obj = {
          timestamp: new Date(),
          data: data
        };

        $window.localStorage.setItem('organicity.markers', JSON.stringify(obj) );
        worldMarkers = obj.data;
      }

      function getEntitiesTimeStamp() {
        return ($window.localStorage.getItem('organicity.assets') && JSON.parse($window.localStorage.getItem('organicity.assets') ).timestamp);
      }

      function areEntitiesMarkersOld() {
        var markersDate = getEntitiesTimeStamp();
        return !timeUtils.isWithin(60, 'seconds', markersDate);
      }

      function removeEntitiesMarkers() {
        $window.localStorage.removeItem('organicity.assets');
      }

      function getTimeStamp() {
        return ($window.localStorage.getItem('organicity.markers') && JSON.parse($window.localStorage.getItem('organicity.markers') ).timestamp);
      }

      function areMarkersOld() {
        var markersDate = getTimeStamp();
        return !timeUtils.isWithin(60, 'seconds', markersDate);
      }

      function removeMarkers() {
        $window.localStorage.removeItem('organicity.markers');
      }
	  }
})();
<|endoftext|>


<commit_before>/*
*
*	Impaler abilities
*
*/
G.abilities[5] =[

// 	First Ability: Electrified Hair
{
	trigger: "onUnderAttack",

	require: function(damage) {
		if (damage === undefined) return false;
		if (!damage.damages.shock) return false;
		return this.testRequirements();
	},

	activate: function(damage) {
		this.end();
		var converted = Math.floor(damage.damages.shock / 4);
		// Lower damage
		damage.damages.shock -= converted;
		// Replenish energy
		// Calculate overflow first; we may need it later
		var energyMissing = this.creature.stats.energy - this.creature.energy;
		var energyOverflow = converted - energyMissing;
		this.creature.recharge(converted);
		// If upgraded and energy overflow, convert into health
		if (this.isUpgraded() && energyOverflow > 0) {
			this.creature.heal(energyOverflow);
		}
		G.log("%CreatureName" + this.creature.id + "% absorbs " + converted + " shock damage into energy");
		return damage;
	}
},

// 	Second Ability: Hasted Javelin
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	// 	require() :
	require : function() {
		if( !this.testRequirements() ) return false;

		if (!this.atLeastOneTarget(this._getHexes(), "enemy")) {
			return false;
		}
		return true;
	},

	// 	query() :
	query : function() {

		var ability = this;
		var creature = this.creature;

		G.grid.queryCreature({
			fnOnConfirm : function() { ability.animation.apply(ability, arguments); },
			team : 0, // Team, 0 = enemies
			id : creature.id,
			flipped : creature.flipped,
			hexs: this._getHexes()
		});
	},

	//	activate() :
	activate : function(target, args) {
		var ability = this;
		ability.end();

		var finalDmg = $j.extend({poison: 0}, ability.damages1);

		// Poison Bonus if upgraded
		if (this.isUpgraded()) {
			finalDmg.poison = this.damages1.poison;
		}

		G.UI.checkAbilities();

		var damage = new Damage(
			ability.creature, // Attacker
			finalDmg, // Damage Type
			1, // Area
			[] // Effects
		);
		var result = target.takeDamage(damage);
		// Recharge movement if any damage dealt
		if (result.damages && result.damages.total > 0) {
			this.creature.remainingMove = this.creature.stats.movement;
			G.log("%CreatureName" + this.creature.id + "%'s movement recharged");
		}
	},

	_getHexes: function() {
		return G.grid.getHexMap(this.creature.x-3, this.creature.y-2, 0, false, frontnback3hex);
	}
},

// 	Thirt Ability: Poisonous Vine
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	// 	require() :
	require : function() {
		if (!this.atLeastOneTarget(this._getHexes(), "enemy")) {
			return false;
		}
		return this.testRequirements();
	},

	// 	query() :
	query : function() {
		var ability = this;
		var creature = this.creature;

		G.grid.queryCreature( {
			fnOnConfirm: function() { ability.animation.apply(ability, arguments); },
			team: 0, // Team, 0 = enemies
			id: creature.id,
			flipped: creature.flipped,
			hexs: this._getHexes()
		});
	},

	activate: function(target) {
		this.end();
		var damages = this.damages;
		// Last 1 turn, or indefinitely if upgraded
		var lifetime = this.isUpgraded() ? 0 : 1;
		target.addEffect(new Effect(
			this.title,
			this.creature,
			target,
			"onStepOut onAttack",
			{
				effectFn: function(effect) {
					G.log("%CreatureName" + effect.target.id + "% is hit by " + effect.name);
					effect.target.takeDamage(new Damage(effect.owner, damages, 1, []));
					effect.deleteEffect();
				},
				turnLifetime: lifetime
			}
		));
	},

	_getHexes: function() {
		// Target a creature within 2 hex radius
		var hexes = G.grid.hexs[this.creature.y][this.creature.x].adjacentHex(2);
		return hexes.extendToLeft(this.creature.size);
	}
},

//	Fourth Ability: Chain Lightning
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	require: function() {
		if (!this.testRequirements()) return false;
		if (!this.atLeastOneTarget(this._getHexes(), "both")) {
			return false;
		}
		return true;
	},

	//	query() :
	query : function(){
		var ability = this;

		G.grid.queryCreature( {
			fnOnConfirm: function() { ability.animation.apply(ability, arguments); },
			team: 3, // Team, 3 = both
			id: this.creature.id,
			flipped: this.creature.flipped,
			hexs: this._getHexes()
		});
	},

	//	activate() :
	activate : function(target) {
		var ability = this;
		ability.end();

		var targets = [];
		targets.push(target); // Add First creature hit
		var nextdmg = $j.extend({},ability.damages); // Copy the object

		// For each Target
		for (var i = 0; i < targets.length; i++) {
			var trg = targets[i];

			// If upgraded and the target is an ally, protect it with an effect that
			// reduces the damage to guarantee at least 1 health remaining
			if (this.isUpgraded() && this.creature.isAlly(trg.team)) {
				trg.addEffect(new Effect(
					this.title,
					this.creature,
					trg,
					"onUnderAttack",
					{
						effectFn: function(effect, damage) {
							// Simulate the damage to determine how much damage would have
							// been dealt; then reduce the damage so that it will not kill
							while (true) {
								var dmg = damage.applyDamage();
								// If we can't reduce any further, give up and have the damage
								// be zero
								if (dmg.total <= 0 || damage.damages.shock <= 0 ||
										trg.health <= 1) {
									damage.damages = {shock: 0};
									break;
								} else if (dmg.total >= trg.health) {
									// Too much damage, would have killed; reduce and try again
									damage.damages.shock--;
								} else {
									break;
								}
							}
						},
						deleteTrigger: "onEndPhase",
						noLog: true
					}
				));
			}

			var damage = new Damage(
				ability.creature, // Attacker
				nextdmg, // Damage Type
				1, // Area
				[] // Effects
			);
			nextdmg = trg.takeDamage(damage);

			if (nextdmg.damages === undefined) break; // If attack is dodge
			if(nextdmg.kill) break; // If target is killed
			if(nextdmg.damages.total <= 0) break; // If damage is too weak
			if (nextdmg.damageObj.status !== "") break;
			delete nextdmg.damages.total;
			nextdmg = nextdmg.damages;

			// Get next available targets
			nextTargets = ability.getTargets(trg.adjacentHexs(1,true));

			nextTargets.filter(function() {
				if (this.hexsHit === undefined) return false; // Remove empty ids
				return (targets.indexOf(this.target) == -1) ; // If this creature has already been hit
			});

			// If no target
			if (nextTargets.length === 0) break;

			// Best Target
			var bestTarget = { size: 0, stats:{ defense:-99999, shock:-99999 } };
			for (var j = 0; j < nextTargets.length; j++) { // For each creature
				if (typeof nextTargets[j] == "undefined") continue; // Skip empty ids.

				var t = nextTargets[j].target;
				// Compare to best target
				if(t.stats.shock > bestTarget.stats.shock){
					if( ( t == ability.creature && nextTargets.length == 1 ) || // If target is chimera and the only target
						t != ability.creature ) { // Or this is not chimera
						bestTarget = t;
					}
				} else {
					continue;
				}

			}

			if( bestTarget instanceof Creature ){
				targets.push(bestTarget);
			}else{
				break;
			}
		}

	},

	_getHexes: function() {
		return G.grid.getHexMap(this.creature.x-3, this.creature.y-2, 0, false, frontnback3hex);
	}
}

];
<commit_msg>Fix Poisonous Vine delete trigger (#976) (#1045)<commit_after>/*
*
*	Impaler abilities
*
*/
G.abilities[5] =[

// 	First Ability: Electrified Hair
{
	trigger: "onUnderAttack",

	require: function(damage) {
		if (damage === undefined) return false;
		if (!damage.damages.shock) return false;
		return this.testRequirements();
	},

	activate: function(damage) {
		this.end();
		var converted = Math.floor(damage.damages.shock / 4);
		// Lower damage
		damage.damages.shock -= converted;
		// Replenish energy
		// Calculate overflow first; we may need it later
		var energyMissing = this.creature.stats.energy - this.creature.energy;
		var energyOverflow = converted - energyMissing;
		this.creature.recharge(converted);
		// If upgraded and energy overflow, convert into health
		if (this.isUpgraded() && energyOverflow > 0) {
			this.creature.heal(energyOverflow);
		}
		G.log("%CreatureName" + this.creature.id + "% absorbs " + converted + " shock damage into energy");
		return damage;
	}
},

// 	Second Ability: Hasted Javelin
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	// 	require() :
	require : function() {
		if( !this.testRequirements() ) return false;

		if (!this.atLeastOneTarget(this._getHexes(), "enemy")) {
			return false;
		}
		return true;
	},

	// 	query() :
	query : function() {

		var ability = this;
		var creature = this.creature;

		G.grid.queryCreature({
			fnOnConfirm : function() { ability.animation.apply(ability, arguments); },
			team : 0, // Team, 0 = enemies
			id : creature.id,
			flipped : creature.flipped,
			hexs: this._getHexes()
		});
	},

	//	activate() :
	activate : function(target, args) {
		var ability = this;
		ability.end();

		var finalDmg = $j.extend({poison: 0}, ability.damages1);

		// Poison Bonus if upgraded
		if (this.isUpgraded()) {
			finalDmg.poison = this.damages1.poison;
		}

		G.UI.checkAbilities();

		var damage = new Damage(
			ability.creature, // Attacker
			finalDmg, // Damage Type
			1, // Area
			[] // Effects
		);
		var result = target.takeDamage(damage);
		// Recharge movement if any damage dealt
		if (result.damages && result.damages.total > 0) {
			this.creature.remainingMove = this.creature.stats.movement;
			G.log("%CreatureName" + this.creature.id + "%'s movement recharged");
		}
	},

	_getHexes: function() {
		return G.grid.getHexMap(this.creature.x-3, this.creature.y-2, 0, false, frontnback3hex);
	}
},

// 	Thirt Ability: Poisonous Vine
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	// 	require() :
	require : function() {
		if (!this.atLeastOneTarget(this._getHexes(), "enemy")) {
			return false;
		}
		return this.testRequirements();
	},

	// 	query() :
	query : function() {
		var ability = this;
		var creature = this.creature;

		G.grid.queryCreature( {
			fnOnConfirm: function() { ability.animation.apply(ability, arguments); },
			team: 0, // Team, 0 = enemies
			id: creature.id,
			flipped: creature.flipped,
			hexs: this._getHexes()
		});
	},

	activate: function(target) {
		this.end();
		var damages = this.damages;
		// Last 1 turn, or indefinitely if upgraded
		var lifetime = this.isUpgraded() ? 0 : 1;
		target.addEffect(new Effect(
			this.title,
			this.creature,
			target,
			"onStepOut onAttack",
			{
				effectFn: function(effect) {
					G.log("%CreatureName" + effect.target.id + "% is hit by " + effect.name);
					effect.target.takeDamage(new Damage(effect.owner, damages, 1, []));
					effect.deleteEffect();
				},
				turnLifetime: lifetime,
				deleteTrigger: "onEndPhase"
			}
		));
	},

	_getHexes: function() {
		// Target a creature within 2 hex radius
		var hexes = G.grid.hexs[this.creature.y][this.creature.x].adjacentHex(2);
		return hexes.extendToLeft(this.creature.size);
	}
},

//	Fourth Ability: Chain Lightning
{
	//	Type : Can be "onQuery", "onStartPhase", "onDamage"
	trigger : "onQuery",

	require: function() {
		if (!this.testRequirements()) return false;
		if (!this.atLeastOneTarget(this._getHexes(), "both")) {
			return false;
		}
		return true;
	},

	//	query() :
	query : function(){
		var ability = this;

		G.grid.queryCreature( {
			fnOnConfirm: function() { ability.animation.apply(ability, arguments); },
			team: 3, // Team, 3 = both
			id: this.creature.id,
			flipped: this.creature.flipped,
			hexs: this._getHexes()
		});
	},

	//	activate() :
	activate : function(target) {
		var ability = this;
		ability.end();

		var targets = [];
		targets.push(target); // Add First creature hit
		var nextdmg = $j.extend({},ability.damages); // Copy the object

		// For each Target
		for (var i = 0; i < targets.length; i++) {
			var trg = targets[i];

			// If upgraded and the target is an ally, protect it with an effect that
			// reduces the damage to guarantee at least 1 health remaining
			if (this.isUpgraded() && this.creature.isAlly(trg.team)) {
				trg.addEffect(new Effect(
					this.title,
					this.creature,
					trg,
					"onUnderAttack",
					{
						effectFn: function(effect, damage) {
							// Simulate the damage to determine how much damage would have
							// been dealt; then reduce the damage so that it will not kill
							while (true) {
								var dmg = damage.applyDamage();
								// If we can't reduce any further, give up and have the damage
								// be zero
								if (dmg.total <= 0 || damage.damages.shock <= 0 ||
										trg.health <= 1) {
									damage.damages = {shock: 0};
									break;
								} else if (dmg.total >= trg.health) {
									// Too much damage, would have killed; reduce and try again
									damage.damages.shock--;
								} else {
									break;
								}
							}
						},
						deleteTrigger: "onEndPhase",
						noLog: true
					}
				));
			}

			var damage = new Damage(
				ability.creature, // Attacker
				nextdmg, // Damage Type
				1, // Area
				[] // Effects
			);
			nextdmg = trg.takeDamage(damage);

			if (nextdmg.damages === undefined) break; // If attack is dodge
			if(nextdmg.kill) break; // If target is killed
			if(nextdmg.damages.total <= 0) break; // If damage is too weak
			if (nextdmg.damageObj.status !== "") break;
			delete nextdmg.damages.total;
			nextdmg = nextdmg.damages;

			// Get next available targets
			nextTargets = ability.getTargets(trg.adjacentHexs(1,true));

			nextTargets.filter(function() {
				if (this.hexsHit === undefined) return false; // Remove empty ids
				return (targets.indexOf(this.target) == -1) ; // If this creature has already been hit
			});

			// If no target
			if (nextTargets.length === 0) break;

			// Best Target
			var bestTarget = { size: 0, stats:{ defense:-99999, shock:-99999 } };
			for (var j = 0; j < nextTargets.length; j++) { // For each creature
				if (typeof nextTargets[j] == "undefined") continue; // Skip empty ids.

				var t = nextTargets[j].target;
				// Compare to best target
				if(t.stats.shock > bestTarget.stats.shock){
					if( ( t == ability.creature && nextTargets.length == 1 ) || // If target is chimera and the only target
						t != ability.creature ) { // Or this is not chimera
						bestTarget = t;
					}
				} else {
					continue;
				}

			}

			if( bestTarget instanceof Creature ){
				targets.push(bestTarget);
			}else{
				break;
			}
		}

	},

	_getHexes: function() {
		return G.grid.getHexMap(this.creature.x-3, this.creature.y-2, 0, false, frontnback3hex);
	}
}

];
<|endoftext|>


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

  angular
  .module('login')
  .controller('LoginController', LoginController);

  function LoginController($document, $log, $state, $rootScope, $mdDialog, $translate, LoginService) {
    var vm = this;
    vm.formStatus = '';
    vm.submit = submit;
    vm.passwordRegex = /^[^\s]+$/;

    function submit(isValid) {
      if(!isValid){
        return;
      }
      if ($rootScope.networkStatusOnline) {
        var user = vm.data.email;
        var pass = vm.data.password;
        var loginUrl = "api/decks/";
        var targetState = "decks";
        LoginService.doLogin(user, pass, loginUrl)
        .then(function(data){
          if(data.status === 200) {
            $state.go(targetState);
          }else{
            alert("Logowanie nieudane!\n\n" + "HTTP: " + data.status + "\n" + data.statusText);
          }
        });
      }else{
          showOfflineLoginAlert();
      }
    }

    function showOfflineLoginAlert() {
      $mdDialog.show(
        $mdDialog.alert()
        .parent(angular.element($document[0].querySelector('#popupContainer')))
        .clickOutsideToClose(false)
        .title($translate.instant('networkAlert-WARNING'))
        .textContent($translate.instant('networkAlert-OFFLINE_LOGIN'))
        .ariaLabel('Alert Dialog')
        .ok($translate.instant('networkAlert-AGREE'))
        );
    }
  }
})();
<commit_msg>sprzątanie po komunikatach o braku sieci<commit_after>(function() {
  'use strict';

  angular
  .module('login')
  .controller('LoginController', LoginController);

  function LoginController($state, LoginService) {
    var vm = this;
    vm.formStatus = '';
    vm.submit = submit;
    vm.passwordRegex = /^[^\s]+$/;

    function submit(isValid) {
      if(!isValid){
        return;
      }
      var user = vm.data.email;
      var pass = vm.data.password;
      var loginUrl = "api/decks/";
      var targetState = "decks";
      LoginService.doLogin(user, pass, loginUrl)
      .then(function(data){
        if(data.status === 200) {
          $state.go(targetState);
        }else{
          alert("Logowanie nieudane!\n\n" + "HTTP: " + data.status + "\n" + data.statusText);
        }
      });
    }
  }
})();
<|endoftext|>


<commit_before>var cards = require("./Cards");

function CardPlayRecord(action,card){
  this.action = action;
  this.card = card;
  if (card instanceof cards.ShipCard){
    this.type = "ship card";
  } else if (card instanceof cards.PonyCard){
    this.type = "pony";
  } else {
    console.warn("Bad card type",card);
  }
}
CardPlayRecord.prototype.matchesGoalConditions = function(goalCondition){
  if(this.type != goalCondition.type || this.action != goalCondition.action){
    return false;
  }
  var that = this;
  return goalCondition.cards.some(function(filterCard){
    return cardFilter(filterCard)(that.card);
  });
};

function ShipRecord(action,pony1,pony2,shipCard){
  this.action = action;
  this.ponyCards = [pony1,pony2];
  this.shipCard = shipCard;
}
ShipRecord.prototype.type = "ship";
ShipRecord.prototype.matchesGoalConditions = function(goalCondition){
  if(this.type != goalCondition.type || this.action != goalCondition.action){
    return false;
  }
  var that=this;
  return goalCondition.cards.every(function(filterCard){
    return that.ponyCards.some(cardFilter(filterCard));
  });
};

function CurrentGoals(game){
  this.game = game;
  this.currentGoals = Array(this.GOAL_LIMIT).fill(null);
  this.turnsPlays = [];
}

CurrentGoals.prototype.GOAL_LIMIT = 3;

CurrentGoals.prototype.cardPlayed = function(card){
  this.turnsPlays.push(new CardPlayRecord("play",card));
  if(card instanceof cards.ShipCard){
    this.formShip(card);
  }
};

CurrentGoals.prototype.breakupShip = function(shipCard){
  var ponies = shipCard.getPonies();
  this.turnsPlays.push(new ShipRecord("destroy",ponies[0],ponies[1],shipCard));
};

CurrentGoals.prototype.formShip = function(shipCard){
  var ponies = shipCard.getPonies();
  this.turnsPlays.push(new ShipRecord("play",ponies[0],ponies[1],shipCard));
};

CurrentGoals.prototype.markedSwapped = function(ponyCard){
  this.turnsPlays.push(new CardPlayRecord("swapped",ponyCard));
};

CurrentGoals.prototype.onTurnBegin = function(){
  this.turnsPlays = [];
  this.replenishGoals();
};

CurrentGoals.prototype.replenishGoals = function(){
  for(var i=0;i<this.GOAL_LIMIT;i++){
    if (this.currentGoals[i] === null){
      this.currentGoals[i] = this.game.decks.drawGoals(1)[0];
    }
  }
};

CurrentGoals.prototype.replaceGoal = function(oldGoal){
  var rId = this.currentGoals.indexOf(oldGoal),
      newGoal = this.game.decks.drawGoals(1)[0];
  this.currentGoals[rId] = newGoal;
  return {id:newGoal.id,position:rId};
};

CurrentGoals.prototype.checkForCompletion = function(n){
  var goal = this.currentGoals[n];
  if(goal === null){
    return false;
  }
  if(goal.goalCondition === undefined){
    console.warn("Goal",goal.name,"is not implemented");
    return false;
  }
  if(goal.goalCondition.action == "play"){
    var matches = this.turnsPlays.filter(function(p){
      return p.matchesGoalConditions(goal.goalCondition);
    });
    return {
      progress:matches.length,
      needed:goal.goalCondition.count //TODO fix count;
    };
  }
};

CurrentGoals.prototype.checkAllForCompletion = function(){
  var that = this;
  for(var i=0;i<this.currentGoals.length;i++){
    if(this.checkForCompletion(i)){
      this.game.hands[this.game.activePlayer].addCard(this.currentGoals[i]);
      this.currentGoals[i] = null;
      //TODO tell players the goal is won
    }
  }
};

function inList(item,list){
  //TODO: maybe check if list isn't a list...
  return list.indexOf(item) >= 0;
}
function samePonyGroupFilter(count){
  return function(cards){
    var names = {},
        highCount = 0;
    cards.forEach(function(card){
      if( names[card.ponyName] === undefined){
        names[card.ponyName] = [card];
      } else {
        names[card.ponyName].push(card);
      }
      if(names[card.ponyName].length > highCount){
        highCount = names[card.ponyName].length;
        if(highCount > count){
          return true;
        }
      }
    });
    return false;
  };
}

/**
 * Returns a filter function, which returns true if none of the filters fail
 * @param  {object} filterObject The filter object
 * @return {function}            The filter function
 */
function cardFilter(filterObject){
  return function(card){
    var filterParts = Object.keys(filterObject);
    for(var i = 0;i<filterParts.length;i++){
      var cardValue = [],
          filterValue = filterObject[filterParts[i]],
          match = false;
      switch (filterParts[i]){
        case "keyword":
          cardValue = card.keywords;
          break;
        case "race":
          cardValue = card.race;
          break;
        case "name":
          cardValue = card.ponyName;
          break;
        case "gender":
          cardValue = card.gender;
          break;
        case "extraIcon":
          cardValue = card.extraIcon;
          break;
        case "count":
          continue; //Ignore count, it's not used here
        default:
          console.warning(filterParts[i]+" is not one of the known filter types");
          continue;
      }
      if (!Array.isArray(cardValue)){
        cardValue = [cardValue];
      }
      if (!Array.isArray(filterValue)){
        filterValue = [filterValue];
      }
      for (var j=0;j<filterValue.length && !match;j++){
        if(cardValue.indexOf(filterValue[j]) >= 0){
          match = true;
        }
      }
      if(!match){
        return false;
      }
    }
    return true;
  };
}

/*
Goal Logic Type:
  Pony: Refers to 1 or more pony cards
  Ship: Refers to a single pony being shipped with 1 or more cards
  Ship Card: Refers to 1 or more ship cards (as aposed to the ship)
  Chain: Refers to a chain of ponies shipped together

Goal Logic methods:
  Create: Completing the condition in a single play (may already be partly completed)
  Exists: The condition must be true at any ponint, may already be true
  Play: Completing the condition with plays only made this turn
  Destroy: Removing the given pony, breaking up a ship or chain
  Swap: Swapping 2 or more ponies on the grid (each pony counts inivially)
  Modify: You change a pony card's keyword ect, has "from" and "too" instead of "cards"

Hooks:
  Pony
    Create/Exists/Play: Pony Play
    Swap: Pony Moved
    Destroy: Pony Removed
    Modify: Pony Modified
  Ship:
    Create/Exists/Play: Ship Formed
    Destroy: Ship Destroy
  Ship Card:
    Create/Exists/Play: Ship Card Play

3 Basic plays:
  Pony & Ship: PonyA, PonyB, Ship
    Pony Play: PonyA
    Ship Card Play: Ship
    Ship Formed: PonyA, Ship, PonyB
  Ship only: PonyA, PonyB, Ship
    Ship Card Play: Ship
    Ship Formed: PonyP, PonyR
  Replace:
    Pony Destory: PonyR
      Ship Destroy: [All ships with PonyR]
    Pony Play: PonyP
      Ship Form: [All the new ships]

Not implemented/Partly implemnted goal cards:
 - Pomf!
 - Friendship is benefits (missing 4 points)
 - Time Travelers Among Us
 - It's Magical: Horns Are Touching
 - It's not evil
 - Shipwrecker
 - Invasive species
 - Budding Curiosity
 - Charity Auction

 - I Swear I'm Not Gay!
 - It's Not EXACTLY Cheating..."
 - "Just Experimenting"
*/

module.exports = {CurrentGoals};
<commit_msg>Reverting fa286e<commit_after><|endoftext|>


<commit_before>import { PinnedHeader, CardBody, PinnableFooter } from './components/pinned-header-footer-card/sections';
import { Exercise, ExerciseWithScroll } from './components/exercise';
import { ExControlButtons } from './components/exercise/controls';
import { APIHandler, APIHandlerBase } from './api';

export {
  APIHandler, APIHandlerBase, CardBody, Exercise, ExControlButtons,
  ExerciseWithScroll, PinnableFooter, PinnedHeader,
};

export SuretyGuard from './components/surety-guard';
export OXRouter from './helpers/router';
export OXLink from './factories/link';
export OXButtonLink from './factories/button-link';
export OXMatchByRouter from './helpers/match-by-router';

export APIActionAdapter from './api/action-adapter';
export ReactHelpers from './helpers/react';

export ArbitraryHtmlAndMath from './components/html';
export Markdown from './components/markdown';
export AsyncButton from './components/buttons/async-button';
export BootstrapURLs from './model/urls';
export ChangeStudentIdForm from './components/change-student-id-form';
export Breadcrumb from './components/breadcrumb';

export ChapterSectionMixin from './components/chapter-section-mixin';
export CloseButton from './components/buttons/close-button';
export CcJoinConflict from './components/enroll/cc-join-conflict';
export ConfirmJoinCourse from './components/enroll/confirm-join-course';
export MessageList from './components/enroll/message-list';

export ExerciseGroup from './components/exercise/group';
export ExerciseIdentifierLink from './components/exercise-identifier-link';
export ExerciseHelpers from './helpers/exercise';
export ExercisePreview from './components/exercise-preview';

export { TaskHelper } from './helpers/task';
export StepHelpsHelper from './helpers/step-helps';
export propHelpers from './helpers/props';
export Logging from './helpers/logging';
export ExerciseIntro from './components/exercise/intro';

export FreeResponse from './components/exercise/free-response';
export GetPositionMixin from './components/get-position-mixin';
export ScrollToMixin from './components/scroll-to-mixin';
export KeysHelper from './helpers/keys';
export NotificationActions from './model/notifications';
export NotificationsBar from './components/notifications/bar';

export PinnedHeaderFooterCard from './components/pinned-header-footer-card';
export Question from './components/question';
export RefreshButton from './components/buttons/refresh-button';
export ResizeListenerMixin from './components/resize-listener-mixin';
export SmartOverflow from './components/smart-overflow';
export { default as SpyMode } from './components/spy-mode';
export HandleBodyClassesMixin from './components/handle-body-classes-mixin';
<commit_msg>export idType for validating either string or number for ids<commit_after>import { PinnedHeader, CardBody, PinnableFooter } from './components/pinned-header-footer-card/sections';
import { Exercise, ExerciseWithScroll } from './components/exercise';
import { ExControlButtons } from './components/exercise/controls';
import { APIHandler, APIHandlerBase } from './api';
import { idType } from './helpers/react';
export {
  APIHandler, APIHandlerBase, CardBody, Exercise, ExControlButtons,
  ExerciseWithScroll, PinnableFooter, PinnedHeader, idType,
};

export SuretyGuard from './components/surety-guard';
export OXRouter from './helpers/router';
export OXLink from './factories/link';
export OXButtonLink from './factories/button-link';
export OXMatchByRouter from './helpers/match-by-router';

export APIActionAdapter from './api/action-adapter';
export ReactHelpers from './helpers/react';

export ArbitraryHtmlAndMath from './components/html';
export Markdown from './components/markdown';
export AsyncButton from './components/buttons/async-button';
export BootstrapURLs from './model/urls';
export ChangeStudentIdForm from './components/change-student-id-form';
export Breadcrumb from './components/breadcrumb';

export ChapterSectionMixin from './components/chapter-section-mixin';
export CloseButton from './components/buttons/close-button';
export CcJoinConflict from './components/enroll/cc-join-conflict';
export ConfirmJoinCourse from './components/enroll/confirm-join-course';
export MessageList from './components/enroll/message-list';

export ExerciseGroup from './components/exercise/group';
export ExerciseIdentifierLink from './components/exercise-identifier-link';
export ExerciseHelpers from './helpers/exercise';
export ExercisePreview from './components/exercise-preview';

export { TaskHelper } from './helpers/task';
export StepHelpsHelper from './helpers/step-helps';
export propHelpers from './helpers/props';
export Logging from './helpers/logging';
export ExerciseIntro from './components/exercise/intro';

export FreeResponse from './components/exercise/free-response';
export GetPositionMixin from './components/get-position-mixin';
export ScrollToMixin from './components/scroll-to-mixin';
export KeysHelper from './helpers/keys';
export NotificationActions from './model/notifications';
export NotificationsBar from './components/notifications/bar';

export PinnedHeaderFooterCard from './components/pinned-header-footer-card';
export Question from './components/question';
export RefreshButton from './components/buttons/refresh-button';
export ResizeListenerMixin from './components/resize-listener-mixin';
export SmartOverflow from './components/smart-overflow';
export { default as SpyMode } from './components/spy-mode';
export HandleBodyClassesMixin from './components/handle-body-classes-mixin';
<|endoftext|>