<commit_before>/*
 * grunt-contrib-qunit
 * http://gruntjs.com/
 *
 * Copyright (c) 2012 "Cowboy" Ben Alman, contributors
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // Nodejs libs.
  var path = require('path');

  // External lib.
  var phantomjs = require('grunt-lib-phantomjs').init(grunt);

  // Keep track of the last-started module, test and status.
  var currentModule, currentTest, status;
  // Keep track of the last-started test(s).
  var unfinished = {};

  // Get an asset file, local to the root of the project.
  var asset = path.join.bind(null, __dirname, '..');

  // Allow an error message to retain its color when split across multiple lines.
  var formatMessage = function(str) {
    return String(str).split('\n').map(function(s) { return s.magenta; }).join('\n');
  };

  // Keep track of failed assertions for pretty-printing.
  var failedAssertions = [];
  var logFailedAssertions = function() {
    var assertion;
    // Print each assertion error.
    while (assertion = failedAssertions.shift()) {
      grunt.verbose.or.error(assertion.testName);
      grunt.log.error('Message: ' + formatMessage(assertion.message));
      if (assertion.actual !== assertion.expected) {
        grunt.log.error('Actual: ' + formatMessage(assertion.actual));
        grunt.log.error('Expected: ' + formatMessage(assertion.expected));
      }
      if (assertion.source) {
        grunt.log.error(assertion.source.replace(/ {4}(at)/g, '  $1'));
      }
      grunt.log.writeln();
    }
  };

  // QUnit hooks.
  phantomjs.on('qunit.moduleStart', function(name) {
    unfinished[name] = true;
    currentModule = name;
  });

  phantomjs.on('qunit.moduleDone', function(name/*, failed, passed, total*/) {
    delete unfinished[name];
  });

  phantomjs.on('qunit.log', function(result, actual, expected, message, source) {
    if (!result) {
      failedAssertions.push({
        actual: actual, expected: expected, message: message, source: source,
        testName: currentTest
      });
    }
  });

  phantomjs.on('qunit.testStart', function(name) {
    currentTest = (currentModule ? currentModule + ' - ' : '') + name;
    grunt.verbose.write(currentTest + '...');
  });

  phantomjs.on('qunit.testDone', function(name, failed/*, passed, total*/) {
    // Log errors if necessary, otherwise success.
    if (failed > 0) {
      // list assertions
      if (grunt.option('verbose')) {
        grunt.log.error();
        logFailedAssertions();
      } else {
        grunt.log.write('F'.red);
      }
    } else {
      grunt.verbose.ok().or.write('.');
    }
  });

  phantomjs.on('qunit.done', function(failed, passed, total, duration) {
    phantomjs.halt();
    status.failed += failed;
    status.passed += passed;
    status.total += total;
    status.duration += duration;
    // Print assertion errors here, if verbose mode is disabled.
    if (!grunt.option('verbose')) {
      if (failed > 0) {
        grunt.log.writeln();
        logFailedAssertions();
      } else {
        grunt.log.ok();
      }
    }
  });

  // Re-broadcast qunit events on grunt.event.
  phantomjs.on('qunit.*', function() {
    var args = [this.event].concat(grunt.util.toArray(arguments));
    grunt.event.emit.apply(grunt.event, args);
  });

  // Built-in error handlers.
  phantomjs.on('fail.load', function(url) {
    phantomjs.halt();
    grunt.verbose.write('Running PhantomJS...').or.write('...');
    grunt.log.error();
    grunt.warn('PhantomJS unable to load "' + url + '" URI.', 90);
  });

  phantomjs.on('fail.timeout', function() {
    phantomjs.halt();
    grunt.log.writeln();
    grunt.warn('PhantomJS timed out, possibly due to a missing QUnit start() call.', 90);
  });

  // Pass-through console.log statements.
  phantomjs.on('console', console.log.bind(console));

  grunt.registerMultiTask('qunit', 'Run QUnit unit tests in a headless PhantomJS instance.', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      // Default PhantomJS timeout.
      timeout: 5000,
      // QUnit-PhantomJS bridge file to be injected.
      inject: asset('phantomjs/bridge.js'),
    });

    // Get files as URLs.
    var urls = grunt.file.expandFileURLs(this.file.srcRaw);

    // This task is asynchronous.
    var done = this.async();

    // Reset status.
    status = {failed: 0, passed: 0, total: 0, duration: 0};

    // Process each filepath in-order.
    grunt.util.async.forEachSeries(urls, function(url, next) {
      var basename = path.basename(url);
      grunt.verbose.subhead('Testing ' + basename).or.write('Testing ' + basename);

      // Reset current module.
      currentModule = null;

      // Launch PhantomJS.
      grunt.event.emit('qunit.spawn', url);
      phantomjs.spawn(url, {
        // Exit code to use if PhantomJS fails in an uncatchable way.
        failCode: 90,
        // Additional PhantomJS options.
        options: options,
        // Do stuff when done.
        done: function(err) {
          if (err) {
            // If there was an error, abort the series.
            done();
          } else {
            // Otherwise, process next url.
            next();
          }
        },
      });
    },
    // All tests have been run.
    function() {
      // Log results.
      if (status.failed > 0) {
        grunt.warn(status.failed + '/' + status.total + ' assertions failed (' +
          status.duration + 'ms)', Math.min(99, 90 + status.failed));
      } else if (status.total === 0) {
        grunt.warn('0/0 assertions ran (' + status.duration + 'ms)');
      } else {
        grunt.verbose.writeln();
        grunt.log.ok(status.total + ' assertions passed (' + status.duration + 'ms)');
      }
      // All done!
      done();
    });
  });

};
<commit_msg>No longer throw custom error codes on failure.<commit_after>/*
 * grunt-contrib-qunit
 * http://gruntjs.com/
 *
 * Copyright (c) 2012 "Cowboy" Ben Alman, contributors
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // Nodejs libs.
  var path = require('path');

  // External lib.
  var phantomjs = require('grunt-lib-phantomjs').init(grunt);

  // Keep track of the last-started module, test and status.
  var currentModule, currentTest, status;
  // Keep track of the last-started test(s).
  var unfinished = {};

  // Get an asset file, local to the root of the project.
  var asset = path.join.bind(null, __dirname, '..');

  // Allow an error message to retain its color when split across multiple lines.
  var formatMessage = function(str) {
    return String(str).split('\n').map(function(s) { return s.magenta; }).join('\n');
  };

  // Keep track of failed assertions for pretty-printing.
  var failedAssertions = [];
  var logFailedAssertions = function() {
    var assertion;
    // Print each assertion error.
    while (assertion = failedAssertions.shift()) {
      grunt.verbose.or.error(assertion.testName);
      grunt.log.error('Message: ' + formatMessage(assertion.message));
      if (assertion.actual !== assertion.expected) {
        grunt.log.error('Actual: ' + formatMessage(assertion.actual));
        grunt.log.error('Expected: ' + formatMessage(assertion.expected));
      }
      if (assertion.source) {
        grunt.log.error(assertion.source.replace(/ {4}(at)/g, '  $1'));
      }
      grunt.log.writeln();
    }
  };

  // QUnit hooks.
  phantomjs.on('qunit.moduleStart', function(name) {
    unfinished[name] = true;
    currentModule = name;
  });

  phantomjs.on('qunit.moduleDone', function(name/*, failed, passed, total*/) {
    delete unfinished[name];
  });

  phantomjs.on('qunit.log', function(result, actual, expected, message, source) {
    if (!result) {
      failedAssertions.push({
        actual: actual, expected: expected, message: message, source: source,
        testName: currentTest
      });
    }
  });

  phantomjs.on('qunit.testStart', function(name) {
    currentTest = (currentModule ? currentModule + ' - ' : '') + name;
    grunt.verbose.write(currentTest + '...');
  });

  phantomjs.on('qunit.testDone', function(name, failed/*, passed, total*/) {
    // Log errors if necessary, otherwise success.
    if (failed > 0) {
      // list assertions
      if (grunt.option('verbose')) {
        grunt.log.error();
        logFailedAssertions();
      } else {
        grunt.log.write('F'.red);
      }
    } else {
      grunt.verbose.ok().or.write('.');
    }
  });

  phantomjs.on('qunit.done', function(failed, passed, total, duration) {
    phantomjs.halt();
    status.failed += failed;
    status.passed += passed;
    status.total += total;
    status.duration += duration;
    // Print assertion errors here, if verbose mode is disabled.
    if (!grunt.option('verbose')) {
      if (failed > 0) {
        grunt.log.writeln();
        logFailedAssertions();
      } else {
        grunt.log.ok();
      }
    }
  });

  // Re-broadcast qunit events on grunt.event.
  phantomjs.on('qunit.*', function() {
    var args = [this.event].concat(grunt.util.toArray(arguments));
    grunt.event.emit.apply(grunt.event, args);
  });

  // Built-in error handlers.
  phantomjs.on('fail.load', function(url) {
    phantomjs.halt();
    grunt.verbose.write('Running PhantomJS...').or.write('...');
    grunt.log.error();
    grunt.warn('PhantomJS unable to load "' + url + '" URI.');
  });

  phantomjs.on('fail.timeout', function() {
    phantomjs.halt();
    grunt.log.writeln();
    grunt.warn('PhantomJS timed out, possibly due to a missing QUnit start() call.');
  });

  // Pass-through console.log statements.
  phantomjs.on('console', console.log.bind(console));

  grunt.registerMultiTask('qunit', 'Run QUnit unit tests in a headless PhantomJS instance.', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var options = this.options({
      // Default PhantomJS timeout.
      timeout: 5000,
      // QUnit-PhantomJS bridge file to be injected.
      inject: asset('phantomjs/bridge.js'),
    });

    // Get files as URLs.
    var urls = grunt.file.expandFileURLs(this.file.srcRaw);

    // This task is asynchronous.
    var done = this.async();

    // Reset status.
    status = {failed: 0, passed: 0, total: 0, duration: 0};

    // Process each filepath in-order.
    grunt.util.async.forEachSeries(urls, function(url, next) {
      var basename = path.basename(url);
      grunt.verbose.subhead('Testing ' + basename).or.write('Testing ' + basename);

      // Reset current module.
      currentModule = null;

      // Launch PhantomJS.
      grunt.event.emit('qunit.spawn', url);
      phantomjs.spawn(url, {
        // Additional PhantomJS options.
        options: options,
        // Do stuff when done.
        done: function(err) {
          if (err) {
            // If there was an error, abort the series.
            done();
          } else {
            // Otherwise, process next url.
            next();
          }
        },
      });
    },
    // All tests have been run.
    function() {
      // Log results.
      if (status.failed > 0) {
        grunt.warn(status.failed + '/' + status.total + ' assertions failed (' +
          status.duration + 'ms)');
      } else if (status.total === 0) {
        grunt.warn('0/0 assertions ran (' + status.duration + 'ms)');
      } else {
        grunt.verbose.writeln();
        grunt.log.ok(status.total + ' assertions passed (' + status.duration + 'ms)');
      }
      // All done!
      done();
    });
  });

};
<|endoftext|>


<commit_before>const Task = require('data.task');
const Async = require('control.async')(Task);
const when = require('when');
const task2Promise = Async.toPromise(when.promise);
const { getType } = require('./typeRegistry');
const shared = require('davis-shared');
const {thread} = shared.fp;
const {isNilOrEmpty} = shared.string;
const queryString = require('../queryString');

module.exports = ({
  graphql,
  dataQuery,
  dataAnalyze,
  dataDelete,
  jobQueue,
  importJob,
  config,
  parseDataFile
}) => {

  const gqlDataQuery = registry => ({
    type: new graphql.GraphQLList(getType('DataSetQueryResults', registry)),
    args: {
      dataSets: {
        type: new graphql.GraphQLList(graphql.GraphQLInt),
        defaultValue: []
      },
      q: {
        type: graphql.GraphQLString,
        defaultValue: ''
      }
    },
    resolve: (_, {dataSets, q}) => {

      const filters = isNilOrEmpty(q) ? [] :
        thread(q,
        queryString.stringToMap,
        queryString.queryFilters.deSerialize);

      return task2Promise(dataQuery(filters, dataSets));
    }
  });

  const gqlDataAnalyze = registry => ({
    type: new graphql.GraphQLList(getType('VariableMatch', registry)),
    args: {
      dataSet: { type: new graphql.GraphQLNonNull(graphql.GraphQLInt) },
      fileId: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) }
    },
    resolve: (_, {dataSet, fileId}) => {
      const filePath = `${config.upload.path}/${fileId}`;
      return task2Promise(dataAnalyze(dataSet, parseDataFile(filePath)));
    }
  });

  const gqlDataImport = registry => ({
    type: getType('Job', registry),
    args: {
      dataSet: { type: new graphql.GraphQLNonNull(graphql.GraphQLInt) },
      fileId: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
      columnMappings: { type: new graphql.GraphQLNonNull(graphql.GraphQLJSON) }
    },
    resolve: (_, {dataSet, columnMappings, fileId}) => {
      const filePath = `${config.upload.path}/${fileId}`;

      return task2Promise(importJob.queue(dataSet, columnMappings, filePath, jobQueue));
    }
  });

  const gqlDataDelete = registryIgnored => ({
    type: graphql.GraphQLBoolean,
    args: {
      dataSet: {
        type: new graphql.GraphQLList(graphql.GraphQLInt),
        defaultValue: []
      },
      variable: {
        type: new graphql.GraphQLList(graphql.GraphQLInt),
        defaultValue: []
      },
      attribute: {
        type: new graphql.GraphQLList(graphql.GraphQLInt),
        defaultValue: []
      }
    },
    resolve: (_, filters) => task2Promise(dataDelete(filters))
  });

  const gqlDataQueries = registry => new graphql.GraphQLObjectType({
    name: 'DataQuery',
    fields: {
      query: gqlDataQuery(registry),
      analyze: gqlDataAnalyze(registry)
    }
  });

  const gqlDataMutation = registry => new graphql.GraphQLObjectType({
    name: 'DataMutation',
    fields: {
      import: gqlDataImport(registry),
      delete: gqlDataDelete(registry)
    }
  });

  return {
    gqlDataQueries,
    gqlDataMutation
  };
};
<commit_msg>Add analyzeColumn endpoint for single column analyze<commit_after>const Task = require('data.task');
const Async = require('control.async')(Task);
const when = require('when');
const task2Promise = Async.toPromise(when.promise);
const { getType } = require('./typeRegistry');
const shared = require('davis-shared');
const {thread} = shared.fp;
const {isNilOrEmpty} = shared.string;
const queryString = require('../queryString');

module.exports = ({
  graphql,
  dataQuery,
  dataAnalyze,
  dataDelete,
  jobQueue,
  importJob,
  config,
  parseDataFile
}) => {

  const gqlDataQuery = registry => ({
    type: new graphql.GraphQLList(getType('DataSetQueryResults', registry)),
    args: {
      dataSets: {
        type: new graphql.GraphQLList(graphql.GraphQLInt),
        defaultValue: []
      },
      q: {
        type: graphql.GraphQLString,
        defaultValue: ''
      }
    },
    resolve: (_, {dataSets, q}) => {

      const filters = isNilOrEmpty(q) ? [] :
        thread(q,
        queryString.stringToMap,
        queryString.queryFilters.deSerialize);

      return task2Promise(dataQuery(filters, dataSets));
    }
  });

  const gqlDataAnalyze = registry => ({
    type: new graphql.GraphQLList(getType('VariableMatch', registry)),
    args: {
      dataSet: { type: new graphql.GraphQLNonNull(graphql.GraphQLInt) },
      fileId: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) }
    },
    resolve: (_, {dataSet, fileId}) => {
      const filePath = `${config.upload.path}/${fileId}`;
      return task2Promise(dataAnalyze(dataSet, parseDataFile(filePath)));
    }
  });

  const gqlDataAnalyzeColumn = registry => ({
    type: getType('VariableMatch', registry),
    args: {
      dataSet: { type: new graphql.GraphQLNonNull(graphql.GraphQLInt) },
      fileId: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
      column: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) }
    },
    resolve: (_, {dataSet, fileId, column}) => {
      const filePath = `${config.upload.path}/${fileId}`;
      return task2Promise(
        dataAnalyze(dataSet, parseDataFile(filePath), column).map(r => r[0]));
    }
  });

  const gqlDataImport = registry => ({
    type: getType('Job', registry),
    args: {
      dataSet: { type: new graphql.GraphQLNonNull(graphql.GraphQLInt) },
      fileId: { type: new graphql.GraphQLNonNull(graphql.GraphQLString) },
      columnMappings: { type: new graphql.GraphQLNonNull(graphql.GraphQLJSON) }
    },
    resolve: (_, {dataSet, columnMappings, fileId}) => {
      const filePath = `${config.upload.path}/${fileId}`;

      return task2Promise(importJob.queue(dataSet, columnMappings, filePath, jobQueue));
    }
  });

  const gqlDataDelete = registryIgnored => ({
    type: graphql.GraphQLBoolean,
    args: {
      dataSet: {
        type: new graphql.GraphQLList(graphql.GraphQLInt),
        defaultValue: []
      },
      variable: {
        type: new graphql.GraphQLList(graphql.GraphQLInt),
        defaultValue: []
      },
      attribute: {
        type: new graphql.GraphQLList(graphql.GraphQLInt),
        defaultValue: []
      }
    },
    resolve: (_, filters) => task2Promise(dataDelete(filters))
  });

  const gqlDataQueries = registry => new graphql.GraphQLObjectType({
    name: 'DataQuery',
    fields: {
      query: gqlDataQuery(registry),
      analyze: gqlDataAnalyze(registry),
      analyzeColumn: gqlDataAnalyzeColumn(registry)
    }
  });

  const gqlDataMutation = registry => new graphql.GraphQLObjectType({
    name: 'DataMutation',
    fields: {
      import: gqlDataImport(registry),
      delete: gqlDataDelete(registry)
    }
  });

  return {
    gqlDataQueries,
    gqlDataMutation
  };
};
<|endoftext|>


<commit_before>const del = require('del');
const env = require('../env');
const gulp = require('gulp');
const gulp_if = require('gulp-if');
const livereload = require('gulp-livereload');
const path = require('path');
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');

const output_dir = 'public/assets/sass';
const sources_dir = 'sources/sass';

gulp.task('sass-clean', () => del(output_dir));

gulp.task('sass', () => gulp.src(path.join(sources_dir, '**.scss'))
	.pipe(gulp_if(env.isDevelopment, sourcemaps.init()))
	.pipe(sass({
		includePaths: [sources_dir],
		outputStyle: 'compressed'
	})).on('error', sass.logError))
	.pipe(gulp_if(env.isDevelopment, sourcemaps.write()))
	.pipe(gulp.dest(output_dir))
	.pipe(livereload()
);

gulp.task('sass-watch', ['sass'], () => gulp.watch(path.join(sources_dir, '**/*.scss'), ['sass']));

module.exports = {
	build: 'sass',
	clean: 'sass-clean',
	watch: 'sass-watch'
};
<commit_msg>fix sass task<commit_after>const del = require('del');
const env = require('../env');
const gulp = require('gulp');
const gulp_if = require('gulp-if');
const livereload = require('gulp-livereload');
const path = require('path');
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');

const output_dir = 'public/assets/sass';
const sources_dir = 'sources/sass';

gulp.task('sass-clean', () => del(output_dir));

gulp.task('sass', () => gulp.src(path.join(sources_dir, '**.scss'))
	.pipe(gulp_if(env.isDevelopment, sourcemaps.init()))
	.pipe(sass({
		includePaths: [sources_dir],
		outputStyle: 'compressed'
	})).on('error', sass.logError)
	.pipe(gulp_if(env.isDevelopment, sourcemaps.write()))
	.pipe(gulp.dest(output_dir))
	.pipe(livereload())
);

gulp.task('sass-watch', ['sass'], () => gulp.watch(path.join(sources_dir, '**/*.scss'), ['sass']));

module.exports = {
	build: 'sass',
	clean: 'sass-clean',
	watch: 'sass-watch'
};
<|endoftext|>


<commit_before>/**
 * Remixer 1: @herkulano (http://www.herkulano.com)
 * Remixer 2: @hotappsfactory (http://www.hotappsfactory.com)
 * Thanks to: Niels Bosma (niels.bosma@motorola.com)
 * Modified by Łukasz 'Severiaan' Grela on 2014/11/19
 */
/*
 #target Illustrator
 */
(function () {

    if (app.documents.length == 0) {
        alert("Open a document containing some artboards to export before running this script");
        return;
    }
    var saveAsPng24 = function (document, filePath, scaleTo) {
        //alert("saveAsPng24(document,"+filePath+")")
        var file = new File(filePath);
        var options = new ExportOptionsPNG24();
        options.antiAliasing = true;
        options.transparency = true;
        options.artBoardClipping = true;
        options.verticalScale = scaleTo || 100;
        options.horizontalScale = scaleTo || 100;
        //
        document.exportFile(file, ExportType.PNG24, options);
    };
    /**
     * Scale and export file suffixed by densitySuffix, in a specific folder named folderName
     */
    var saveToRes = function (document, scaleTo, preffix, densitySuffix, folderName, lowerCase) {
            var i, ab, file;

            var myFolder = new Folder(folder.absoluteURI + "/" + folderName);
            if (!myFolder.exists) myFolder.create();

            for (i = document.artboards.length - 1; i >= 0; i--) {
                document.artboards.setActiveArtboardIndex(i);
                ab = document.artboards[i];

                var fileName = preffix + ab.name + densitySuffix;

                if (lowerCase) {
                    fileName = fileName.toLowerCase();
                }
                // save
                saveAsPng24(document, myFolder.fsName + "/" + fileName + ".png", scaleTo);
            }
        }
    //application
    var folder = Folder.selectDialog();
    var document = app.activeDocument;
    var suffix;

    if (document && folder) {
        var documentName = document.name.replace(".ai", "");

        saveToRes(document, 100, "", "", documentName + "/ios", true);
        //saveToRes(document, 200, "", "@2x", documentName+"/ios", true);
        //saveToRes(document, 300, "", "@3x", documentName+"/ios", true);
    }

})();<commit_msg>save 3 resolution per artboard, instead of running 3times over artboards<commit_after>/**
 * Remixer 1: @herkulano (http://www.herkulano.com)
 * Remixer 2: @hotappsfactory (http://www.hotappsfactory.com)
 * Thanks to: Niels Bosma (niels.bosma@motorola.com)
 * Modified by Łukasz 'Severiaan' Grela on 2014/11/19
 */
/*
 #target Illustrator
 */
(function() {
    if (app.documents.length == 0) {
        alert('Open a document containing some artboards to export before running this script');
        return;
    }
    var saveAsPng24 = function(document, filePath, scaleTo) {
        //alert("saveAsPng24(document,"+filePath+")")
        var file = new File(filePath);
        var options = new ExportOptionsPNG24();
        options.antiAliasing = true;
        options.transparency = true;
        options.artBoardClipping = true;
        options.verticalScale = scaleTo || 100;
        options.horizontalScale = scaleTo || 100;
        //
        document.exportFile(file, ExportType.PNG24, options);
    };
    /**
     * Scale and export file suffixed by densitySuffix, in a specific folder named folderName
     */
    var saveToRes = function(document, scaleTo, preffix, densitySuffix, folderName, lowerCase) {
        var i, ab, file;

        var myFolder = new Folder(folder.absoluteURI + '/' + folderName);
        if (!myFolder.exists) myFolder.create();

        for (i = document.artboards.length - 1; i >= 0; i--) {
            document.artboards.setActiveArtboardIndex(i);
            ab = document.artboards[i];

            var fileName = preffix + ab.name + densitySuffix;

            if (lowerCase) {
                fileName = fileName.toLowerCase();
            }
            // save
            saveAsPng24(document, myFolder.fsName + '/' + fileName + '.png', scaleTo);
            saveAsPng24(document, myFolder.fsName + '/' + fileName + '@2x.png', scaleTo * 2);
            saveAsPng24(document, myFolder.fsName + '/' + fileName + '@3x.png', scaleTo * 3);
        }
    };
    //application
    var folder = Folder.selectDialog();
    var document = app.activeDocument;
    var suffix;

    if (document && folder) {
        var documentName = document.name.replace('.ai', '');

        saveToRes(document, 100, '', '', documentName + '/ios', true);
    }
})();
<|endoftext|>


<commit_before>/**
 * @ngdoc directive
 * @name info-window
 * @param Attr2MapOptions {service}
 *   convert html attribute to Google map api options
 * @param $compile {service} $compile service
 * @description
 *  Defines infoWindow and provides compile method
 *
 *  Requires:  map directive
 *
 *  Restrict To:  Element
 *
 *  NOTE: this directive should **NOT** be used with `ng-repeat`
 *  because InfoWindow itself is a template, and a template must be
 *  reused by each marker, thus, should not be redefined repeatedly
 *  by `ng-repeat`.
 *
 * @attr {Boolean} visible
 *   Indicates to show it when map is initialized
 * @attr {Boolean} visible-on-marker
 *   Indicates to show it on a marker when map is initialized
 * @attr {Expression} geo-callback
 *   if position is an address, the expression is will be performed
 *   when geo-lookup is successful. e.g., geo-callback="showDetail()"
 * @attr {String} <InfoWindowOption> Any InfoWindow options,
 *   https://developers.google.com/maps/documentation/javascript/reference?csw=1#InfoWindowOptions
 * @attr {String} <InfoWindowEvent> Any InfoWindow events,
 *   https://developers.google.com/maps/documentation/javascript/reference
 * @example
 * Usage:
 *   <map MAP_ATTRIBUTES>
 *    <info-window id="foo" ANY_OPTIONS ANY_EVENTS"></info-window>
 *   </map>
 *
 * Example:
 *  <map center="41.850033,-87.6500523" zoom="3">
 *    <info-window id="1" position="41.850033,-87.6500523" >
 *

 *        Chicago, IL

 *        LatLng: {{chicago.lat()}}, {{chicago.lng()}},

 *        World Coordinate: {{worldCoordinate.x}}, {{worldCoordinate.y}},

 *        Pixel Coordinate: {{pixelCoordinate.x}}, {{pixelCoordinate.y}},

 *        Tile Coordinate: {{tileCoordinate.x}}, {{tileCoordinate.y}} at Zoom Level {{map.getZoom()}}
 *

 *    </info-window>
 *  </map>
 */
/* global google */
(function() {
  'use strict';

  var infoWindow = function(Attr2MapOptions, $compile, $q, $templateRequest, $timeout, $parse, NgMap)  {
    var parser = Attr2MapOptions;

    var getInfoWindow = function(options, events, element) {
      var infoWindow;

      /**
       * set options
       */
      if (options.position && !(options.position instanceof google.maps.LatLng)) {
        delete options.position;
      }
      infoWindow = new google.maps.InfoWindow(options);

      /**
       * set events
       */
      for (var eventName in events) {
        if (eventName) {
          google.maps.event.addListener(infoWindow, eventName, events[eventName]);
        }
      }

      /**
       * set template and template-related functions
       * it must have a container element with ng-non-bindable
       */
      var templatePromise = $q(function(resolve) {
        if (angular.isString(element)) {
          $templateRequest(element).then(function (requestedTemplate) {
            resolve(angular.element(requestedTemplate).wrap('
').parent());
          }, function(message) {
            throw "info-window template request failed: " + message;
          });
        }
        else {
          resolve(element);
        }
      }).then(function(resolvedTemplate) {
        var template = resolvedTemplate.html().trim();
        if (angular.element(template).length != 1) {
          throw "info-window working as a template must have a container";
        }
        infoWindow.__template = template.replace(/\s?ng-non-bindable[='"]+/,"");
      });

      infoWindow.__open = function(map, scope, anchor) {
        templatePromise.then(function() {
          $timeout(function() {
            anchor && (scope.anchor = anchor);
            var el = $compile(infoWindow.__template)(scope);
            infoWindow.setContent(el[0]);
            scope.$apply();
            if (anchor && anchor.getPosition) {
              infoWindow.open(map, anchor);
            } else if (anchor && anchor instanceof google.maps.LatLng) {
              infoWindow.open(map);
              infoWindow.setPosition(anchor);
            } else {
              infoWindow.open(map);
            }
            var infoWindowContainerEl = infoWindow.content.parentElement.parentElement.parentElement;
            infoWindowContainerEl.className = "ng-map-info-window";
          });
        });
      };

      return infoWindow;
    };

    var linkFunc = function(scope, element, attrs, mapController) {
      mapController = mapController[0]||mapController[1];

      element.css('display','none');

      var orgAttrs = parser.orgAttributes(element);
      var filtered = parser.filter(attrs);
      var options = parser.getOptions(filtered, {scope: scope});
      var events = parser.getEvents(scope, filtered);

      var infoWindow = getInfoWindow(options, events, options.template || element);
      var address;
      if (options.position && !(options.position instanceof google.maps.LatLng)) {
        address = options.position;
      }
      if (address) {
        NgMap.getGeoLocation(address).then(function(latlng) {
          infoWindow.setPosition(latlng);
          infoWindow.__open(mapController.map, scope, latlng);
          var geoCallback = attrs.geoCallback;
          geoCallback && $parse(geoCallback)(scope);
        });
      }

      mapController.addObject('infoWindows', infoWindow);
      mapController.observeAttrSetObj(orgAttrs, attrs, infoWindow);

      mapController.showInfoWindow =
      mapController.map.showInfoWindow = mapController.showInfoWindow ||
        function(p1, p2, p3) { //event, id, marker
          var id = typeof p1 == 'string' ? p1 : p2;
          var marker = typeof p1 == 'string' ? p2 : p3;
          if (typeof marker == 'string') {
            //Check if markers if defined to avoid odd 'undefined' errors
            if (typeof mapController.map.markers != "undefined"
                && typeof mapController.map.markers[marker] != "undefined") {
              marker = mapController.map.markers[marker];
            } else if (
                //additionally check if that marker is a custom marker
            typeof mapController.map.customMarkers
            && typeof mapController.map.customMarkers[marker] != "undefined") {
              marker = mapController.map.customMarkers[marker];
            } else {
              //Better error output if marker with that id is not defined
              throw new Error("Cant open info window for id " + marker + ". Marker or CustomMarker is not defined")
            }
          }

          var infoWindow = mapController.map.infoWindows[id];
          var anchor = marker ? marker : (this.getPosition ? this : null);
          infoWindow.__open(mapController.map, scope, anchor);
          if(mapController.singleInfoWindow) {
            if(mapController.lastInfoWindow) {
              scope.hideInfoWindow(mapController.lastInfoWindow);
            }
            mapController.lastInfoWindow = id;
          }
        };

      mapController.hideInfoWindow =
      mapController.map.hideInfoWindow = mapController.hideInfoWindow ||
        function(p1, p2) {
          var id = typeof p1 == 'string' ? p1 : p2;
          var infoWindow = mapController.map.infoWindows[id];
          infoWindow.close();
        };

      //TODO DEPRECATED
      scope.showInfoWindow = mapController.map.showInfoWindow;
      scope.hideInfoWindow = mapController.map.hideInfoWindow;

      var map = infoWindow.mapId ? {id:infoWindow.mapId} : 0;
      NgMap.getMap(map).then(function(map) {
        infoWindow.visible && infoWindow.__open(map, scope);
        if (infoWindow.visibleOnMarker) {
          var markerId = infoWindow.visibleOnMarker;
          infoWindow.__open(map, scope, map.markers[markerId]);
        }
      });

    }; //link

    return {
      restrict: 'E',
      require: ['?^map','?^ngMap'],
      link: linkFunc
    };

  }; // infoWindow
  infoWindow.$inject =
    ['Attr2MapOptions', '$compile', '$q', '$templateRequest', '$timeout', '$parse', 'NgMap'];

  angular.module('ngMap').directive('infoWindow', infoWindow);
})();
<commit_msg>issue #701 fix for type check<commit_after>/**
 * @ngdoc directive
 * @name info-window
 * @param Attr2MapOptions {service}
 *   convert html attribute to Google map api options
 * @param $compile {service} $compile service
 * @description
 *  Defines infoWindow and provides compile method
 *
 *  Requires:  map directive
 *
 *  Restrict To:  Element
 *
 *  NOTE: this directive should **NOT** be used with `ng-repeat`
 *  because InfoWindow itself is a template, and a template must be
 *  reused by each marker, thus, should not be redefined repeatedly
 *  by `ng-repeat`.
 *
 * @attr {Boolean} visible
 *   Indicates to show it when map is initialized
 * @attr {Boolean} visible-on-marker
 *   Indicates to show it on a marker when map is initialized
 * @attr {Expression} geo-callback
 *   if position is an address, the expression is will be performed
 *   when geo-lookup is successful. e.g., geo-callback="showDetail()"
 * @attr {String} <InfoWindowOption> Any InfoWindow options,
 *   https://developers.google.com/maps/documentation/javascript/reference?csw=1#InfoWindowOptions
 * @attr {String} <InfoWindowEvent> Any InfoWindow events,
 *   https://developers.google.com/maps/documentation/javascript/reference
 * @example
 * Usage:
 *   <map MAP_ATTRIBUTES>
 *    <info-window id="foo" ANY_OPTIONS ANY_EVENTS"></info-window>
 *   </map>
 *
 * Example:
 *  <map center="41.850033,-87.6500523" zoom="3">
 *    <info-window id="1" position="41.850033,-87.6500523" >
 *

 *        Chicago, IL

 *        LatLng: {{chicago.lat()}}, {{chicago.lng()}},

 *        World Coordinate: {{worldCoordinate.x}}, {{worldCoordinate.y}},

 *        Pixel Coordinate: {{pixelCoordinate.x}}, {{pixelCoordinate.y}},

 *        Tile Coordinate: {{tileCoordinate.x}}, {{tileCoordinate.y}} at Zoom Level {{map.getZoom()}}
 *

 *    </info-window>
 *  </map>
 */
/* global google */
(function() {
  'use strict';

  var infoWindow = function(Attr2MapOptions, $compile, $q, $templateRequest, $timeout, $parse, NgMap)  {
    var parser = Attr2MapOptions;

    var getInfoWindow = function(options, events, element) {
      var infoWindow;

      /**
       * set options
       */
      if (options.position && !(options.position instanceof google.maps.LatLng)) {
        delete options.position;
      }
      infoWindow = new google.maps.InfoWindow(options);

      /**
       * set events
       */
      for (var eventName in events) {
        if (eventName) {
          google.maps.event.addListener(infoWindow, eventName, events[eventName]);
        }
      }

      /**
       * set template and template-related functions
       * it must have a container element with ng-non-bindable
       */
      var templatePromise = $q(function(resolve) {
        if (angular.isString(element)) {
          $templateRequest(element).then(function (requestedTemplate) {
            resolve(angular.element(requestedTemplate).wrap('
').parent());
          }, function(message) {
            throw "info-window template request failed: " + message;
          });
        }
        else {
          resolve(element);
        }
      }).then(function(resolvedTemplate) {
        var template = resolvedTemplate.html().trim();
        if (angular.element(template).length != 1) {
          throw "info-window working as a template must have a container";
        }
        infoWindow.__template = template.replace(/\s?ng-non-bindable[='"]+/,"");
      });

      infoWindow.__open = function(map, scope, anchor) {
        templatePromise.then(function() {
          $timeout(function() {
            anchor && (scope.anchor = anchor);
            var el = $compile(infoWindow.__template)(scope);
            infoWindow.setContent(el[0]);
            scope.$apply();
            if (anchor && anchor.getPosition) {
              infoWindow.open(map, anchor);
            } else if (anchor && anchor instanceof google.maps.LatLng) {
              infoWindow.open(map);
              infoWindow.setPosition(anchor);
            } else {
              infoWindow.open(map);
            }
            var infoWindowContainerEl = infoWindow.content.parentElement.parentElement.parentElement;
            infoWindowContainerEl.className = "ng-map-info-window";
          });
        });
      };

      return infoWindow;
    };

    var linkFunc = function(scope, element, attrs, mapController) {
      mapController = mapController[0]||mapController[1];

      element.css('display','none');

      var orgAttrs = parser.orgAttributes(element);
      var filtered = parser.filter(attrs);
      var options = parser.getOptions(filtered, {scope: scope});
      var events = parser.getEvents(scope, filtered);

      var infoWindow = getInfoWindow(options, events, options.template || element);
      var address;
      if (options.position && !(options.position instanceof google.maps.LatLng)) {
        address = options.position;
      }
      if (address) {
        NgMap.getGeoLocation(address).then(function(latlng) {
          infoWindow.setPosition(latlng);
          infoWindow.__open(mapController.map, scope, latlng);
          var geoCallback = attrs.geoCallback;
          geoCallback && $parse(geoCallback)(scope);
        });
      }

      mapController.addObject('infoWindows', infoWindow);
      mapController.observeAttrSetObj(orgAttrs, attrs, infoWindow);

      mapController.showInfoWindow =
      mapController.map.showInfoWindow = mapController.showInfoWindow ||
        function(p1, p2, p3) { //event, id, marker
          var id = typeof p1 == 'string' ? p1 : p2;
          var marker = typeof p1 == 'string' ? p2 : p3;
          if (typeof marker == 'string') {
            //Check if markers if defined to avoid odd 'undefined' errors
            if (
              typeof mapController.map.markers != "undefined"
              && typeof mapController.map.markers[marker] != "undefined") {
                marker = mapController.map.markers[marker];
            } else if (
              //additionally check if that marker is a custom marker
              typeof mapController.map.customMarkers !== "undefined"
              && typeof mapController.map.customMarkers[marker] !== "undefined") {
                marker = mapController.map.customMarkers[marker];
            } else {
              //Better error output if marker with that id is not defined
              throw new Error("Cant open info window for id " + marker + ". Marker or CustomMarker is not defined")
            }
          }

          var infoWindow = mapController.map.infoWindows[id];
          var anchor = marker ? marker : (this.getPosition ? this : null);
          infoWindow.__open(mapController.map, scope, anchor);
          if(mapController.singleInfoWindow) {
            if(mapController.lastInfoWindow) {
              scope.hideInfoWindow(mapController.lastInfoWindow);
            }
            mapController.lastInfoWindow = id;
          }
        };

      mapController.hideInfoWindow =
      mapController.map.hideInfoWindow = mapController.hideInfoWindow ||
        function(p1, p2) {
          var id = typeof p1 == 'string' ? p1 : p2;
          var infoWindow = mapController.map.infoWindows[id];
          infoWindow.close();
        };

      //TODO DEPRECATED
      scope.showInfoWindow = mapController.map.showInfoWindow;
      scope.hideInfoWindow = mapController.map.hideInfoWindow;

      var map = infoWindow.mapId ? {id:infoWindow.mapId} : 0;
      NgMap.getMap(map).then(function(map) {
        infoWindow.visible && infoWindow.__open(map, scope);
        if (infoWindow.visibleOnMarker) {
          var markerId = infoWindow.visibleOnMarker;
          infoWindow.__open(map, scope, map.markers[markerId]);
        }
      });

    }; //link

    return {
      restrict: 'E',
      require: ['?^map','?^ngMap'],
      link: linkFunc
    };

  }; // infoWindow
  infoWindow.$inject =
    ['Attr2MapOptions', '$compile', '$q', '$templateRequest', '$timeout', '$parse', 'NgMap'];

  angular.module('ngMap').directive('infoWindow', infoWindow);
})();
<|endoftext|>


<commit_before>var App = function(router)
{
	this.router = router;
};

	// Starts the application
App.prototype.start = function()
{
	this.router.listen(8181);
}

App.$inject = [ "Router" ];
module.exports = App;
<commit_msg>Fixed tab space<commit_after>var App = function(router)
{
	this.router = router;
};

// Starts the application
App.prototype.start = function()
{
	this.router.listen(8181);
}

App.$inject = [ "Router" ];
module.exports = App;
<|endoftext|>


<commit_before>//miniQuery
//2014, Marcel Duin <https://github.com/marcelduin/>

$ = function(s){return new _$(s)};

$.extend = function(){
	var a = arguments, r = a[0]===true, o = a[r&&1||0];
	function cp(i,o) { for(var x in i) { var p = i[x], c = p&&p.constructor; o[x] = (r&&c&&(c==Array||c==Object)) ? cp(p,new c) : (r&&c&&(c==Number||c==String)) ? c(p) : p; } return o };
	for(var i=(r?2:1);i<a.length;i++) cp(a[i],o);
	return o;
};

function _getEls(sel,par){
	if(sel==window) return [window];
	if(sel instanceof Element) return [sel];
	if(sel instanceof Array || sel instanceof _$) return sel;
	if(/^\</.test(sel)) {var fr = document.createElement('div');fr.innerHTML = sel;return fr.childNodes;}
	if(sel) return (par||document).querySelectorAll(sel);
	return [];
};

function _$(sel,par){ var _=_getEls(sel,par); for(var x in _) this[x]=_[x]; if(!this.length) this.length = _.length; };
_$.prototype = {
	each        : function(f)    { for(var i=0;i<this.length;i++) f.call(this[i]); return this },
	remove      : function()     { this.each(function(){this.parentNode.removeChild(this)}); return this },
	replaceWith : function(el)   { var me = this; if(me[0]) { if(el.each) el.each(function(){ me[0].parentNode.insertBefore(this,me[0]); }); else me[0].parentNode.insertBefore(el,me[0]); me.remove(); } return this },
	appendTo    : function(el)   { el=el.length?el[0]:el;this.each(function(){el.appendChild(this)}); return this },
	parent      : function()     { var r = [];this.each(function(){r.push(this.parentNode)});return new _$(r); },
	children    : function(sel)  { sel = sel || '*';var ce = [];this.each(function(){var e = this.querySelectorAll(sel);for(var i=0;i<e.length;i++) if(e[i].parentNode==this) ce.push(e[i]);}); return new _$(ce) },
	find        : function(sel)  { return new _$(sel,this[0]) },
	filter      : function(s,iv) { s = _getEls(s); return new _$([].filter.call(this,function(n){ for(var i=0;i<s.length;i++) if(s[i]==n) return !iv; return !!iv })) },
	not         : function(sel)  { return this.filter(sel,true) },
	eq          : function(i)    { return new _$(this[i]) },
	has         : function(el)   { for(var i=0;i<this.length;i++) if(this[i]==el) return true },
	add         : function(sel)  { sel = _getEls(sel); var me = this, cu = []; for(var i=0;i<this.length;i++) cu.push(this[i]); var ta = cu.concat([].filter.call(sel,function(n){return cu.indexOf(n)==-1})); return ta.length==this.length?this:new _$(ta) },
	attr        : function(k,v)  { if(v===undefined) return this[0]&&this[0].getAttribute(k); this.each(function(){this[((v===null)?'remove':'set')+'Attribute'](k,v)}); return this },
	trigger     : function(e,v)  { this.each(function(){var evt = !isIE?new CustomEvent(e,{detail:v}):document.createEvent('CustomEvent');if(isIE) evt.initCustomEvent(e, false, false, v);this.dispatchEvent(evt)}); return this },
	on          : function(e,f)  { e=e.split(' '); this.each(function(){for(var x in e) this.addEventListener(e[x],f)}); return this },
	off         : function(e,f)  { e=e.split(' '); this.each(function(){for(var x in e) this.removeEventListener(e[x],f)}); return this },
	click       : function(f)    { if(f instanceof Function) this.on('click',f); else this.trigger('click'); return this },
	text        : function(t)    { if(t===undefined) return this[0]&&this[0].textContent; this.each(function(){this.textContent=t}); return this },
	html        : function(h)    { if(t===undefined) return this[0]&&this[0].innerHTML; this.each(function(){this.innerHTML=h}); return this },
	hasClass    : function(cl,h) { h=0;this.each(function(){h+=this.classList.contains(cl)&&1||0});return !!h },
	addClass    : function(cl)   { cl=cl.split(' ');this.each(function(){for(var i in cl) this.classList.add(cl[i])});return this },
	removeClass : function(cl)   { cl=cl.split(' ');this.each(function(){for(var i in cl) this.classList.remove(cl[i])});return this },
	toggleClass : function(cl)   { cl=cl.split(' ');for(var x in cl) this[(this.hasClass(cl[x])?'remove':'add')+'Class'](cl[x]); return this },
	setcss      : function(v,p)  { this.each(function(){this.style.setProperty(v,p)}); return this },
	getcss      : function(p)    { return this[0]&&this[0].style.getPropertyValue(p); },
	css         : function(a,b)  { if(typeof a == 'string') if(b===undefined) return this.getcss(a); else this.setcss(a,b);else for(var x in a) this.setcss(x,a[x]); return this },
	hide        : function()     { this.setcss('display','none'); return this },
	show        : function()     { this.setcss('display','block'); return this },
	width       : function()     { return this[0]&&this[0].clientWidth },
	height      : function()     { return this[0]&&this[0].clientHeight }
};
<commit_msg>.parent() returns unique<commit_after>//miniQuery
//2014, Marcel Duin <https://github.com/marcelduin/>

$ = function(s){return new _$(s)};

$.extend = function(){
	var a = arguments, r = a[0]===true, o = a[r&&1||0];
	function cp(i,o) { for(var x in i) { var p = i[x], c = p&&p.constructor; o[x] = (r&&c&&(c==Array||c==Object)) ? cp(p,new c) : (r&&c&&(c==Number||c==String)) ? c(p) : p; } return o };
	for(var i=(r?2:1);i<a.length;i++) cp(a[i],o);
	return o;
};

function _getEls(sel,par){
	if(sel==window) return [window];
	if(sel instanceof Element) return [sel];
	if(sel instanceof Array || sel instanceof _$) return sel;
	if(/^\</.test(sel)) {var fr = document.createElement('div');fr.innerHTML = sel;return fr.childNodes;}
	if(sel) return (par||document).querySelectorAll(sel);
	return [];
};

function _$(sel,par){ var _=_getEls(sel,par); for(var x in _) this[x]=_[x]; if(!this.length) this.length = _.length; };
_$.prototype = {
	each        : function(f)    { for(var i=0;i<this.length;i++) f.call(this[i]); return this },
	remove      : function()     { this.each(function(){this.parentNode.removeChild(this)}); return this },
	replaceWith : function(el)   { var me = this; if(me[0]) { if(el.each) el.each(function(){ me[0].parentNode.insertBefore(this,me[0]); }); else me[0].parentNode.insertBefore(el,me[0]); me.remove(); } return this },
	appendTo    : function(el)   { el=el.length?el[0]:el;this.each(function(){el.appendChild(this)}); return this },
	parent      : function()     { var r = [];this.each(function(){if(r.indexOf(this.parentNode)<0) r.push(this.parentNode)});return new _$(r); },
	children    : function(sel)  { sel = sel || '*';var ce = [];this.each(function(){var e = this.querySelectorAll(sel);for(var i=0;i<e.length;i++) if(e[i].parentNode==this) ce.push(e[i]);}); return new _$(ce) },
	find        : function(sel)  { return new _$(sel,this[0]) },
	filter      : function(s,iv) { s = _getEls(s); return new _$([].filter.call(this,function(n){ for(var i=0;i<s.length;i++) if(s[i]==n) return !iv; return !!iv })) },
	not         : function(sel)  { return this.filter(sel,true) },
	eq          : function(i)    { return new _$(this[i]) },
	has         : function(el)   { for(var i=0;i<this.length;i++) if(this[i]==el) return true },
	add         : function(sel)  { sel = _getEls(sel); var me = this, cu = []; for(var i=0;i<this.length;i++) cu.push(this[i]); var ta = cu.concat([].filter.call(sel,function(n){return cu.indexOf(n)==-1})); return ta.length==this.length?this:new _$(ta) },
	attr        : function(k,v)  { if(v===undefined) return this[0]&&this[0].getAttribute(k); this.each(function(){this[((v===null)?'remove':'set')+'Attribute'](k,v)}); return this },
	trigger     : function(e,v)  { this.each(function(){var evt = !isIE?new CustomEvent(e,{detail:v}):document.createEvent('CustomEvent');if(isIE) evt.initCustomEvent(e, false, false, v);this.dispatchEvent(evt)}); return this },
	on          : function(e,f)  { e=e.split(' '); this.each(function(){for(var x in e) this.addEventListener(e[x],f)}); return this },
	off         : function(e,f)  { e=e.split(' '); this.each(function(){for(var x in e) this.removeEventListener(e[x],f)}); return this },
	click       : function(f)    { if(f instanceof Function) this.on('click',f); else this.trigger('click'); return this },
	text        : function(t)    { if(t===undefined) return this[0]&&this[0].textContent; this.each(function(){this.textContent=t}); return this },
	html        : function(h)    { if(t===undefined) return this[0]&&this[0].innerHTML; this.each(function(){this.innerHTML=h}); return this },
	hasClass    : function(cl,h) { h=0;this.each(function(){h+=this.classList.contains(cl)&&1||0});return !!h },
	addClass    : function(cl)   { cl=cl.split(' ');this.each(function(){for(var i in cl) this.classList.add(cl[i])});return this },
	removeClass : function(cl)   { cl=cl.split(' ');this.each(function(){for(var i in cl) this.classList.remove(cl[i])});return this },
	toggleClass : function(cl)   { cl=cl.split(' ');for(var x in cl) this[(this.hasClass(cl[x])?'remove':'add')+'Class'](cl[x]); return this },
	setcss      : function(v,p)  { this.each(function(){this.style.setProperty(v,p)}); return this },
	getcss      : function(p)    { return this[0]&&this[0].style.getPropertyValue(p); },
	css         : function(a,b)  { if(typeof a == 'string') if(b===undefined) return this.getcss(a); else this.setcss(a,b);else for(var x in a) this.setcss(x,a[x]); return this },
	hide        : function()     { this.setcss('display','none'); return this },
	show        : function()     { this.setcss('display','block'); return this },
	width       : function()     { return this[0]&&this[0].clientWidth },
	height      : function()     { return this[0]&&this[0].clientHeight }
};
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import {Link, withRouter} from 'react-router'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import SourceIndicator from 'shared/components/SourceIndicator'
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'

import {createDashboard} from 'src/dashboards/apis'
import {getDashboardsAsync, deleteDashboardAsync} from 'src/dashboards/actions'

import {NEW_DASHBOARD} from 'src/dashboards/constants'

const {
  arrayOf,
  func,
  string,
  shape,
} = PropTypes

const DashboardsPage = React.createClass({
  propTypes: {
    source: shape({
      id: string.isRequired,
      name: string.isRequired,
      type: string,
      links: shape({
        proxy: string.isRequired,
      }).isRequired,
      telegraf: string.isRequired,
    }),
    router: shape({
      push: func.isRequired,
    }).isRequired,
    addFlashMessage: func,
    handleGetDashboards: func.isRequired,
    handleDeleteDashboard: func.isRequired,
    dashboards: arrayOf(shape()),
  },

  componentDidMount() {
    this.props.handleGetDashboards()
  },

  async handleCreateDashbord() {
    const {source: {id}, router: {push}} = this.props
    const {data} = await createDashboard(NEW_DASHBOARD)
    push(`/sources/${id}/dashboards/${data.id}`)
  },

  handleDeleteDashboard(dashboard) {
    this.props.handleDeleteDashboard(dashboard)
  },

  render() {
    const {dashboards: dashboards} = this.props
    const dashboardLink = `/sources/${this.props.source.id}`
    let tableHeader
    if (dashboards === null) {
      tableHeader = "Loading Dashboards..."
    } else if (dashboards.length === 0) {
      tableHeader = "1 Dashboard"
    } else {
      tableHeader = `${dashboards.length + 1} Dashboards`
    }

    return (

                Dashboards

              <SourceIndicator sourceName={this.props.source.name} />

{tableHeader}

                    <button className="btn btn-sm btn-primary" onClick={this.handleCreateDashbord}>Create Dashboard</button>

                          Name

                          {
                            dashboards && dashboards.length ?
                            dashboards.map((dashboard) => {
                              return (

                                    <Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
                                      {dashboard.name}
                                    </Link>

                                  <DeleteConfirmTableCell onDelete={this.handleDeleteDashboard} item={dashboard} />

                              );
                            }) :
                            null
                          }

                              <Link to={`${dashboardLink}/kubernetes`}>
                                {'Kubernetes'}
                              </Link>

    )
  },
})

const mapStateToProps = ({dashboardUI: {dashboards, dashboard}}) => ({
  dashboards,
  dashboard,
})

const mapDispatchToProps = (dispatch) => ({
  handleGetDashboards: bindActionCreators(getDashboardsAsync, dispatch),
  handleDeleteDashboard: bindActionCreators(deleteDashboardAsync, dispatch),
})

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(DashboardsPage))
<commit_msg>Use simpler destructuring shorthand<commit_after>import React, {PropTypes} from 'react'
import {Link, withRouter} from 'react-router'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import SourceIndicator from 'shared/components/SourceIndicator'
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'

import {createDashboard} from 'src/dashboards/apis'
import {getDashboardsAsync, deleteDashboardAsync} from 'src/dashboards/actions'

import {NEW_DASHBOARD} from 'src/dashboards/constants'

const {
  arrayOf,
  func,
  string,
  shape,
} = PropTypes

const DashboardsPage = React.createClass({
  propTypes: {
    source: shape({
      id: string.isRequired,
      name: string.isRequired,
      type: string,
      links: shape({
        proxy: string.isRequired,
      }).isRequired,
      telegraf: string.isRequired,
    }),
    router: shape({
      push: func.isRequired,
    }).isRequired,
    addFlashMessage: func,
    handleGetDashboards: func.isRequired,
    handleDeleteDashboard: func.isRequired,
    dashboards: arrayOf(shape()),
  },

  componentDidMount() {
    this.props.handleGetDashboards()
  },

  async handleCreateDashbord() {
    const {source: {id}, router: {push}} = this.props
    const {data} = await createDashboard(NEW_DASHBOARD)
    push(`/sources/${id}/dashboards/${data.id}`)
  },

  handleDeleteDashboard(dashboard) {
    this.props.handleDeleteDashboard(dashboard)
  },

  render() {
    const {dashboards} = this.props
    const dashboardLink = `/sources/${this.props.source.id}`
    let tableHeader
    if (dashboards === null) {
      tableHeader = "Loading Dashboards..."
    } else if (dashboards.length === 0) {
      tableHeader = "1 Dashboard"
    } else {
      tableHeader = `${dashboards.length + 1} Dashboards`
    }

    return (

                Dashboards

              <SourceIndicator sourceName={this.props.source.name} />

{tableHeader}

                    <button className="btn btn-sm btn-primary" onClick={this.handleCreateDashbord}>Create Dashboard</button>

                          Name

                          {
                            dashboards && dashboards.length ?
                            dashboards.map((dashboard) => {
                              return (

                                    <Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
                                      {dashboard.name}
                                    </Link>

                                  <DeleteConfirmTableCell onDelete={this.handleDeleteDashboard} item={dashboard} />

                              );
                            }) :
                            null
                          }

                              <Link to={`${dashboardLink}/kubernetes`}>
                                {'Kubernetes'}
                              </Link>

    )
  },
})

const mapStateToProps = ({dashboardUI: {dashboards, dashboard}}) => ({
  dashboards,
  dashboard,
})

const mapDispatchToProps = (dispatch) => ({
  handleGetDashboards: bindActionCreators(getDashboardsAsync, dispatch),
  handleDeleteDashboard: bindActionCreators(deleteDashboardAsync, dispatch),
})

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(DashboardsPage))
<|endoftext|>


<commit_before>const ee = require('ee')
const {map, switchMap, toArray} = require('rx/operators')
const {calculateIndex} = require('sepal/ee/optical/indexes')
const imageFactory = require('sepal/ee/imageFactory')
const {concat, of, zip} = require('rx')
const _ = require('lodash')
const recipeRef = require('sepal/ee/recipeRef')

const classify =
    ({
        model: {
            inputImagery: {images: imageRecipes},
            legend,
            trainingData: {dataSets},
            auxiliaryImagery = [],
            classifier: classifierConfig,
            scale
        }
    },
    {selection: selectedBands} = {selection: []}
    ) => {
        const recipeTrainingData$ = zip(...dataSets
            .filter(({type}) => type === 'RECIPE')
            .map(({recipe}) =>
                recipeRef({id: recipe}).getRecipe$().pipe(
                    switchMap(recipe => recipe.getTrainingData$())
                ))
        ).pipe(
            map(trainingDataSets => ee.FeatureCollection(trainingDataSets).flatten())
        )
        const referenceData = dataSets
            .filter(({type}) => type !== 'RECIPE')
            .map(({referenceData}) => referenceData)
            .flat()
        const toFeature = plot => {
            return ee.Feature(ee.Geometry.Point([plot['x'], plot['y']]), {'class': plot['class']})
        }
        const referenceDataCollection = ee.FeatureCollection(referenceData.map(toFeature))
        const images$ = () => zip(
            ...imageRecipes.map(recipe => toImage$(recipe, auxiliaryImagery))
        )
        const getTrainingData$ = bands => {
            return images$().pipe(
                switchMap(images =>
                    concat(
                        recipeTrainingData$,
                        of(referenceDataCollection).pipe(
                            map(referenceDataCollection => {
                                const imageToClassify = ee.Image(images)
                                return imageToClassify.uint16().sampleRegions({
                                    collection: referenceDataCollection.filterBounds(imageToClassify.geometry()),
                                    properties: ['class'],
                                    scale: scale || 1
                                })
                            })
                        )
                    ).pipe(
                        toArray(),
                        map(trainingDataSets =>
                            ee.FeatureCollection(trainingDataSets)
                                .flatten()
                                .set('band_order', bands || ee.Image(images).bandNames())
                        )
                    )
                )
            )
        }

        const classify = (trainingData, imageToClassify) => {
            const classifier = classifierConfig.type === 'DECISION_TREE'
                ? createDecisionTreeClassifier(classifierConfig.decisionTree)
                : createClassifier(classifierConfig)
                    .train(trainingData, 'class')
                    .setOutputMode('CLASSIFICATION')
            return imageToClassify
                .classify(classifier)
                .uint8()
                .rename(['class'])
        }

        const createRegression = (trainingData, imageToClassify) => {
            const classifier = createClassifier(classifierConfig)
                .train(trainingData, 'class')
                .setOutputMode('REGRESSION')
            return imageToClassify
                .classify(classifier)
                .float()
                .rename(['regression'])
        }

        const calculateClassProbability = (trainingData, imageToClassify, classification) => {
            const probabilities = legend.entries.map(
                ({value}) =>
                    calculateProbability(trainingData, imageToClassify, `probability_${value}`)
                        .where(classification.neq(value), 0)
            )
            return ee.Image(probabilities).reduce(ee.Reducer.max())
                .rename('class_probability')
        }

        const calculateProbability = (trainingData, imageToClassify, bandName) => {
            const legendValue = parseInt(bandName.match(/probability_(.*)/)[1])
            const classifier = createClassifier(classifierConfig)
                .train(
                    trainingData
                        .map(feature => feature.set('class', feature.getNumber('class').eq(legendValue))),
                    'class'
                )
                .setOutputMode('PROBABILITY')
            return imageToClassify
                .classify(classifier)
                .multiply(100)
                .uint8()
                .rename([bandName])
        }

        const classifyImage = (imageToClassify, selectedBands, trainingData) => {
            const bands = []
            if (selectedBands.includes('class') || selectedBands.includes('class_probability')) {
                const classification = classify(trainingData, imageToClassify)
                if (selectedBands.includes('class')) {
                    bands.push(classification)
                }
                if (selectedBands.includes('class_probability')) {
                    const classProbability = calculateClassProbability(trainingData, imageToClassify, classification)
                    bands.push(classProbability)
                }
            }
            if (selectedBands.includes('regression') || selectedBands.includes('class_probability')) {
                const regression = createRegression(trainingData, imageToClassify)
                bands.push(regression)
            }
            const probabilityBands = selectedBands
                .filter(bandName => bandName.startsWith('probability_'))
                .map(bandName => calculateProbability(trainingData, imageToClassify, bandName))
            bands.push(probabilityBands)
            return ee.Image(bands.flat())
        }

        return {
            getTrainingData$,
            getImage$() {
                return images$().pipe(
                    switchMap(images => {
                        const imageToClassify = ee.Image(images)
                        return getTrainingData$(imageToClassify.bandNames()).pipe(
                            map(trainingData => classifyImage(imageToClassify, selectedBands, trainingData))
                        )
                    })
                )
            },
            getVisParams$() {
                const sortedLegend = _.sortBy(legend.entries, 'value')
                const min = sortedLegend[0].value
                const max = _.last(sortedLegend).value
                const legendPalette = sortedLegend.map(({color}) => color)
                const probabilityPalette = '#000000,#480000,#710101,#BA0000,#FF0000,#FFA500,#FFFF00,#79C900,#006400'
                if (selectedBands.includes('class')) {
                    return of({bands: 'class', min, max, palette: legendPalette})
                } else if (selectedBands.includes('regression')) {
                    return of({bands: 'regression', min, max, palette: legendPalette})
                } else if (selectedBands.includes('class_probability')) {
                    return of({bands: 'class_probability', min: 0, max: 100, palette: probabilityPalette})
                } else {
                    const probabilityBands = selectedBands
                        .filter(bandName => bandName.startsWith('probability_'))
                    if (probabilityBands.length) {
                        return of({bands: probabilityBands[0], min: 0, max: 100, palette: probabilityPalette})
                    } else {
                        throw new Error(`Expected selected bands to contain class, regression, class_probability, or probability_*: ${JSON.stringify(selectedBands)}`)
                    }
                }
            },
            getGeometry$() {
                return images$().pipe(
                    map(images => ee.ImageCollection(images).geometry(scale))
                )
            },
            classifyImage(image, bands, trainingData) {
                if (imageRecipes.length > 1) {
                    throw new Error('This recipe contains more than one inputImage. Cannot classify it')
                }
                const covariates = addCovariates(image, imageRecipes[0].bandSetSpecs, auxiliaryImagery)
                const imageWithCovariates = image.addBands(covariates, null, true)
                return classifyImage(imageWithCovariates, bands, trainingData)
            }
        }
    }

const toImage$ = (recipe, auxiliaryImagery) =>
    imageFactory(recipe).getImage$().pipe(
        map(image => addCovariates(image, recipe.bandSetSpecs, auxiliaryImagery))
    )

const addCovariates = (image, bandSetSpecs, auxiliaryImagery) => {
    return ee.Image(
        bandSetSpecs.map(({type, included, operation}) => {
            switch (type) {
            case 'IMAGE_BANDS':
                return image.selectExisting(included).addBands(
                    calculateIndexes(
                        image.select(
                            image.bandNames().filter(ee.Filter(
                                ee.Filter.inList('item', included).not()
                            ))
                        ),
                        included
                    ), null, true
                )
            case 'PAIR_WISE_EXPRESSION':
                return combinePairwise(image, included, operation)
            case 'INDEXES':
                return calculateIndexes(image, included)
            }
        })
    ).addBands(
        auxiliaryImagery.length && getAuxiliaryImagery(auxiliaryImagery)
    ).updateMask(
        image.mask().reduce(ee.Reducer.max())
    )

}

const getAuxiliaryImagery = auxiliaryImagery =>
    ee.Image(
        auxiliaryImagery.map(type => {
            switch (type) {
            case 'LATITUDE':
                return createLatitudeImage()
            case 'TERRAIN':
                return createTerrainImage()
            case 'WATER':
                return createSurfaceWaterImage()
            }
        })
    )

const createLatitudeImage = () =>
    ee.Image.pixelLonLat().select('latitude').float()

const createTerrainImage = () => {
    const elevation = ee.Image('USGS/SRTMGL1_003')
    const topography = ee.Algorithms.Terrain(elevation)
    const aspectRad = topography.select(['aspect']).multiply(ee.Number(Math.PI).divide(180))
    const eastness = aspectRad.sin().rename(['eastness']).float()
    const northness = aspectRad.cos().rename(['northness']).float()
    return topography.select(['elevation', 'slope', 'aspect'])
        .addBands(eastness)
        .addBands(northness)
}

const createSurfaceWaterImage = () => {
    const water = ee.Image('JRC/GSW1_0/GlobalSurfaceWater').unmask()
    const transitions = [
        'no_change',
        'permanent',
        'new_permanent',
        'lost_permanent',
        'seasonal',
        'new_seasonal',
        'lost_seasonal',
        'seasonal_to_permanent',
        'permanent_to_seasonal',
        'ephemeral_permanent',
        'ephemeral_seasonal'
    ]
    const transitionMasks = ee.Image(
        transitions.map((transition, i) =>
            water.select('transition').eq(i).rename(`water_${transition}`))
    )

    return water
        .select(
            ['occurrence', 'change_abs', 'change_norm', 'seasonality', 'max_extent'],
            ['water_occurrence', 'water_change_abs', 'water_change_norm', 'water_seasonality', 'water_max_extent']
        )
        .addBands(transitionMasks)
}

const combinePairwise = (image, bands, operation) => {
    const operations = {
        RATIO: 'b1 / b2',
        NORMALIZED_DIFFERENCE: '(b1 - b2) / (b1 + b2)',
        DIFFERENCE: 'b1 - b2',
        DISTANCE: 'atan2(b1, b2) / PI',
        ANGLE: 'hypot(b1, b2)'
    }
    return image
        .selectExisting(bands)
        .combinePairwise(operations[operation], `_${operation.toLowerCase()}`)
}

const calculateIndexes = (image, indexNames) =>
    ee.Image(
        indexNames.map(indexName => calculateIndex(image, indexName)
        )
    )

const createDecisionTreeClassifier = decisionTree => {
    try {
        decisionTree = JSON.parse(decisionTree)
        // eslint-disable-next-line no-empty
    } catch (e) {
    } // Probably a single decision tree string
    if (_.isArray(decisionTree)) {
        return ee.Classifier.decisionTreeEnsemble(decisionTree)
    } else if (_.isString(decisionTree)) {
        return ee.Classifier.decisionTree(decisionTree)
    } else {
        throw new Error('Decision tree must either be a JSON array with decision trees or a single decision tree string')
    }
}

const createClassifier = ({type, ...config}) => {
    const randomForest = ({numberOfTrees, variablesPerSplit, minLeafPopulation, bagFraction, maxNodes, seed}) =>
        ee.Classifier.smileRandomForest({
            numberOfTrees: toInt(numberOfTrees),
            variablesPerSplit: toInt(variablesPerSplit),
            minLeafPopulation: toInt(minLeafPopulation),
            bagFraction: toFloat(bagFraction),
            maxNodes: toInt(maxNodes),
            seed: toInt(seed)
        })

    const cart = ({minLeafPopulation, maxNodes}) =>
        ee.Classifier.smileCart({
            minLeafPopulation: toInt(minLeafPopulation),
            maxNodes: toInt(maxNodes)
        })

    const naiveBayes = ({lambda}) =>
        ee.Classifier.smileNaiveBayes({lambda: toFloat(lambda)})

    const svm = ({decisionProcedure, svmType, kernelType, shrinking, degree, gamma, coef0, cost, nu, oneClass}) =>
        ee.Classifier.libsvm({
            decisionProcedure,
            svmType,
            kernelType,
            shrinking,
            degree: kernelType === 'POLY' ? toInt(degree) : null,
            gamma: ['POLY', 'RBF', 'SIGMOID'].includes(kernelType) ? toFloat(gamma) : null,
            coef0: ['POLY', 'SIGMOID'].includes(kernelType) ? toFloat(coef0) : null,
            cost: svmType === 'C_SVC' ? toFloat(cost) : null,
            nu: svmType === 'NU_SVC' ? toFloat(nu) : null,
            oneClass: svmType === 'ONE_CLASS' ? toInt(oneClass) : null
        })

    const minimumDistance = ({metric}) =>
        ee.Classifier.minimumDistance({metric})

    switch (type) {
    case 'RANDOM_FOREST':
        return randomForest(config)
    case 'CART':
        return cart(config)
    case 'NAIVE_BAYES':
        return naiveBayes(config)
    case 'SVM':
        return svm(config)
    case 'MINIMUM_DISTANCE':
        return minimumDistance(config)
    }
}

const toInt = input => {
    input = _.isString(input) ? input : _.toString(input)
    const parsed = parseInt(input)
    return _.isFinite(parsed) ? parsed : null
}

const toFloat = input => {
    input = _.isString(input) ? input : _.toString(input)
    const parsed = parseFloat(input)
    return _.isFinite(parsed) ? parsed : null
}

module.exports = classify
<commit_msg>Switched classification output mode to MULTIPROBABILITY when calculating probabilities.<commit_after>const ee = require('ee')
const {map, switchMap, toArray} = require('rx/operators')
const {calculateIndex} = require('sepal/ee/optical/indexes')
const imageFactory = require('sepal/ee/imageFactory')
const {concat, of, zip} = require('rx')
const _ = require('lodash')
const recipeRef = require('sepal/ee/recipeRef')

const classify =
    ({
        model: {
            inputImagery: {images: imageRecipes},
            legend,
            trainingData: {dataSets},
            auxiliaryImagery = [],
            classifier: classifierConfig,
            scale
        }
    },
    {selection: selectedBands} = {selection: []}
    ) => {
        const recipeTrainingData$ = zip(...dataSets
            .filter(({type}) => type === 'RECIPE')
            .map(({recipe}) =>
                recipeRef({id: recipe}).getRecipe$().pipe(
                    switchMap(recipe => recipe.getTrainingData$())
                ))
        ).pipe(
            map(trainingDataSets => ee.FeatureCollection(trainingDataSets).flatten())
        )
        const referenceData = dataSets
            .filter(({type}) => type !== 'RECIPE')
            .map(({referenceData}) => referenceData)
            .flat()
        const toFeature = plot => {
            return ee.Feature(ee.Geometry.Point([plot['x'], plot['y']]), {'class': plot['class']})
        }
        const referenceDataCollection = ee.FeatureCollection(referenceData.map(toFeature))
        const images$ = () => zip(
            ...imageRecipes.map(recipe => toImage$(recipe, auxiliaryImagery))
        )
        const getTrainingData$ = bands => {
            return images$().pipe(
                switchMap(images =>
                    concat(
                        recipeTrainingData$,
                        of(referenceDataCollection).pipe(
                            map(referenceDataCollection => {
                                const imageToClassify = ee.Image(images)
                                return imageToClassify.uint16().sampleRegions({
                                    collection: referenceDataCollection.filterBounds(imageToClassify.geometry()),
                                    properties: ['class'],
                                    scale: scale || 1
                                })
                            })
                        )
                    ).pipe(
                        toArray(),
                        map(trainingDataSets =>
                            ee.FeatureCollection(trainingDataSets)
                                .flatten()
                                .set('band_order', bands || ee.Image(images).bandNames())
                        )
                    )
                )
            )
        }

        const classify = (trainingData, imageToClassify) => {
            const classifier = classifierConfig.type === 'DECISION_TREE'
                ? createDecisionTreeClassifier(classifierConfig.decisionTree)
                : createClassifier(classifierConfig)
                    .train(trainingData, 'class')
                    .setOutputMode('CLASSIFICATION')
            return imageToClassify
                .classify(classifier)
                .uint8()
                .rename(['class'])
        }

        const createRegression = (trainingData, imageToClassify) => {
            const classifier = createClassifier(classifierConfig)
                .train(trainingData, 'class')
                .setOutputMode('REGRESSION')
            return imageToClassify
                .classify(classifier)
                .float()
                .rename(['regression'])
        }

        const calculateClassProbability = (trainingData, imageToClassify, classification) => {
            const probabilities = calculateProbabilities(trainingData, imageToClassify)
            const multipliers = ee.Image(legend.entries.map(({value}) =>
                ee.Image(1)
                    .where(classification.neq(value), 0)
                    .rename(`probability_${value}`)
            ))
            return probabilities
                .multiply(multipliers)
                .reduce(ee.Reducer.max())
                .rename('class_probability')
        }

        const calculateProbabilities = (trainingData, imageToClassify) => {
            const classifier = createClassifier(classifierConfig)
                .train(trainingData, 'class')
                .setOutputMode('MULTIPROBABILITY')
            const probabilityArrayImage = imageToClassify
                .classify(classifier)
                .multiply(100)
                .uint8()
            const classes = ee.List(classifier.explain().get('classes'))
            const indexes = ee.List.sequence(0, classes.size().subtract(1))
            return ee.Image(classes.zip(indexes).iterate((valueIndex, acc) => {
                const value = ee.List(valueIndex).getNumber(0).int()
                const index = ee.List(valueIndex).getNumber(1).int()
                return ee.Image(acc).addBands(
                    probabilityArrayImage.arrayGet(index)
                        .rename(ee.String('probability_').cat(value.format()))
                )
            }, ee.Image([])))
        }

        const classifyImage = (imageToClassify, selectedBands, trainingData) => {
            const bands = []
            if (selectedBands.includes('class') || selectedBands.includes('class_probability')) {
                const classification = classify(trainingData, imageToClassify)
                if (selectedBands.includes('class')) {
                    bands.push(classification)
                }
                if (selectedBands.includes('class_probability')) {
                    const classProbability = calculateClassProbability(trainingData, imageToClassify, classification)
                    bands.push(classProbability)
                }
            }
            if (selectedBands.includes('regression')) {
                const regression = createRegression(trainingData, imageToClassify)
                bands.push(regression)
            }
            const probabilityBands = selectedBands
                .filter(bandName => bandName.startsWith('probability_'))
            if (probabilityBands.length) {
                const probabilities = calculateProbabilities(trainingData, imageToClassify)
                    .select(probabilityBands)
                bands.push(probabilities)
            }
            return ee.Image(bands.flat())
        }

        return {
            getTrainingData$,
            getImage$() {
                return images$().pipe(
                    switchMap(images => {
                        const imageToClassify = ee.Image(images)
                        return getTrainingData$(imageToClassify.bandNames()).pipe(
                            map(trainingData => classifyImage(imageToClassify, selectedBands, trainingData))
                        )
                    })
                )
            },
            getVisParams$() {
                const sortedLegend = _.sortBy(legend.entries, 'value')
                const min = sortedLegend[0].value
                const max = _.last(sortedLegend).value
                const legendPalette = sortedLegend.map(({color}) => color)
                const probabilityPalette = '#000000,#480000,#710101,#BA0000,#FF0000,#FFA500,#FFFF00,#79C900,#006400'
                if (selectedBands.includes('class')) {
                    return of({bands: 'class', min, max, palette: legendPalette})
                } else if (selectedBands.includes('regression')) {
                    return of({bands: 'regression', min, max, palette: legendPalette})
                } else if (selectedBands.includes('class_probability')) {
                    return of({bands: 'class_probability', min: 0, max: 100, palette: probabilityPalette})
                } else {
                    const probabilityBands = selectedBands
                        .filter(bandName => bandName.startsWith('probability_'))
                    if (probabilityBands.length) {
                        return of({bands: probabilityBands[0], min: 0, max: 100, palette: probabilityPalette})
                    } else {
                        throw new Error(`Expected selected bands to contain class, regression, class_probability, or probability_*: ${JSON.stringify(selectedBands)}`)
                    }
                }
            },
            getGeometry$() {
                return images$().pipe(
                    map(images => ee.ImageCollection(images).geometry(scale))
                )
            },
            classifyImage(image, bands, trainingData) {
                if (imageRecipes.length > 1) {
                    throw new Error('This recipe contains more than one inputImage. Cannot classify it')
                }
                const covariates = addCovariates(image, imageRecipes[0].bandSetSpecs, auxiliaryImagery)
                const imageWithCovariates = image.addBands(covariates, null, true)
                return classifyImage(imageWithCovariates, bands, trainingData)
            }
        }
    }

const toImage$ = (recipe, auxiliaryImagery) =>
    imageFactory(recipe).getImage$().pipe(
        map(image => addCovariates(image, recipe.bandSetSpecs, auxiliaryImagery))
    )

const addCovariates = (image, bandSetSpecs, auxiliaryImagery) => {
    return ee.Image(
        bandSetSpecs.map(({type, included, operation}) => {
            switch (type) {
            case 'IMAGE_BANDS':
                return image.selectExisting(included).addBands(
                    calculateIndexes(
                        image.select(
                            image.bandNames().filter(ee.Filter(
                                ee.Filter.inList('item', included).not()
                            ))
                        ),
                        included
                    ), null, true
                )
            case 'PAIR_WISE_EXPRESSION':
                return combinePairwise(image, included, operation)
            case 'INDEXES':
                return calculateIndexes(image, included)
            }
        })
    ).addBands(
        auxiliaryImagery.length && getAuxiliaryImagery(auxiliaryImagery)
    ).updateMask(
        image.mask().reduce(ee.Reducer.max())
    )

}

const getAuxiliaryImagery = auxiliaryImagery =>
    ee.Image(
        auxiliaryImagery.map(type => {
            switch (type) {
            case 'LATITUDE':
                return createLatitudeImage()
            case 'TERRAIN':
                return createTerrainImage()
            case 'WATER':
                return createSurfaceWaterImage()
            }
        })
    )

const createLatitudeImage = () =>
    ee.Image.pixelLonLat().select('latitude').float()

const createTerrainImage = () => {
    const elevation = ee.Image('USGS/SRTMGL1_003')
    const topography = ee.Algorithms.Terrain(elevation)
    const aspectRad = topography.select(['aspect']).multiply(ee.Number(Math.PI).divide(180))
    const eastness = aspectRad.sin().rename(['eastness']).float()
    const northness = aspectRad.cos().rename(['northness']).float()
    return topography.select(['elevation', 'slope', 'aspect'])
        .addBands(eastness)
        .addBands(northness)
}

const createSurfaceWaterImage = () => {
    const water = ee.Image('JRC/GSW1_0/GlobalSurfaceWater').unmask()
    const transitions = [
        'no_change',
        'permanent',
        'new_permanent',
        'lost_permanent',
        'seasonal',
        'new_seasonal',
        'lost_seasonal',
        'seasonal_to_permanent',
        'permanent_to_seasonal',
        'ephemeral_permanent',
        'ephemeral_seasonal'
    ]
    const transitionMasks = ee.Image(
        transitions.map((transition, i) =>
            water.select('transition').eq(i).rename(`water_${transition}`))
    )

    return water
        .select(
            ['occurrence', 'change_abs', 'change_norm', 'seasonality', 'max_extent'],
            ['water_occurrence', 'water_change_abs', 'water_change_norm', 'water_seasonality', 'water_max_extent']
        )
        .addBands(transitionMasks)
}

const combinePairwise = (image, bands, operation) => {
    const operations = {
        RATIO: 'b1 / b2',
        NORMALIZED_DIFFERENCE: '(b1 - b2) / (b1 + b2)',
        DIFFERENCE: 'b1 - b2',
        DISTANCE: 'atan2(b1, b2) / PI',
        ANGLE: 'hypot(b1, b2)'
    }
    return image
        .selectExisting(bands)
        .combinePairwise(operations[operation], `_${operation.toLowerCase()}`)
}

const calculateIndexes = (image, indexNames) =>
    ee.Image(
        indexNames.map(indexName => calculateIndex(image, indexName)
        )
    )

const createDecisionTreeClassifier = decisionTree => {
    try {
        decisionTree = JSON.parse(decisionTree)
        // eslint-disable-next-line no-empty
    } catch (e) {
    } // Probably a single decision tree string
    if (_.isArray(decisionTree)) {
        return ee.Classifier.decisionTreeEnsemble(decisionTree)
    } else if (_.isString(decisionTree)) {
        return ee.Classifier.decisionTree(decisionTree)
    } else {
        throw new Error('Decision tree must either be a JSON array with decision trees or a single decision tree string')
    }
}

const createClassifier = ({type, ...config}) => {
    const randomForest = ({numberOfTrees, variablesPerSplit, minLeafPopulation, bagFraction, maxNodes, seed}) =>
        ee.Classifier.smileRandomForest({
            numberOfTrees: toInt(numberOfTrees),
            variablesPerSplit: toInt(variablesPerSplit),
            minLeafPopulation: toInt(minLeafPopulation),
            bagFraction: toFloat(bagFraction),
            maxNodes: toInt(maxNodes),
            seed: toInt(seed)
        })

    const cart = ({minLeafPopulation, maxNodes}) =>
        ee.Classifier.smileCart({
            minLeafPopulation: toInt(minLeafPopulation),
            maxNodes: toInt(maxNodes)
        })

    const naiveBayes = ({lambda}) =>
        ee.Classifier.smileNaiveBayes({lambda: toFloat(lambda)})

    const svm = ({decisionProcedure, svmType, kernelType, shrinking, degree, gamma, coef0, cost, nu, oneClass}) =>
        ee.Classifier.libsvm({
            decisionProcedure,
            svmType,
            kernelType,
            shrinking,
            degree: kernelType === 'POLY' ? toInt(degree) : null,
            gamma: ['POLY', 'RBF', 'SIGMOID'].includes(kernelType) ? toFloat(gamma) : null,
            coef0: ['POLY', 'SIGMOID'].includes(kernelType) ? toFloat(coef0) : null,
            cost: svmType === 'C_SVC' ? toFloat(cost) : null,
            nu: svmType === 'NU_SVC' ? toFloat(nu) : null,
            oneClass: svmType === 'ONE_CLASS' ? toInt(oneClass) : null
        })

    const minimumDistance = ({metric}) =>
        ee.Classifier.minimumDistance({metric})

    switch (type) {
    case 'RANDOM_FOREST':
        return randomForest(config)
    case 'CART':
        return cart(config)
    case 'NAIVE_BAYES':
        return naiveBayes(config)
    case 'SVM':
        return svm(config)
    case 'MINIMUM_DISTANCE':
        return minimumDistance(config)
    }
}

const toInt = input => {
    input = _.isString(input) ? input : _.toString(input)
    const parsed = parseInt(input)
    return _.isFinite(parsed) ? parsed : null
}

const toFloat = input => {
    input = _.isString(input) ? input : _.toString(input)
    const parsed = parseFloat(input)
    return _.isFinite(parsed) ? parsed : null
}

module.exports = classify
<|endoftext|>


<commit_before>/*
 * express-lingua
 * A i18n middleware for the Express.js framework.
 *
 * Licensed under the MIT:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright (c) 2011, André König (andre.koenig -[at]- gmail [*dot*] com)
 *
 */
var Guru = require('./guru');
var Trainee = require('./trainee');

module.exports = function(app, options) {

    var _name = 'lingua';

    //
    // The lingua configuration object.
    //
    var configuration = {
        storage: {
            key: 'language'
        },
        resources: {
            defaultLocale: options.defaultLocale,
            path: options.path,
            serialisation: '.json'
        }
    };

    //
    // Verify the given parameters.
    //
    // So the middleware init call should look like:
    //
    //     app.configure(function() {
    //         // Lingua configuration
    //         app.use(lingua(app, {
    //             defaultLocale: 'en',
    //             path: __dirname + '/i18n'
    //         }));
    //     });
    //
    // It is necessary to define the "default locale" and the "path"
    // where lingua finds the i18n resource files.
    //
    if (!configuration.resources.defaultLocale) {
        throw new Error(_name + ': Please define a default locale while registering the middleware.');
    }

    if (!configuration.resources.path) {
        throw new Error(_name + ': Please define a path where ' + _name +  ' can find your locales.');
    } else {
        if (configuration.resources.path[configuration.resources.path.length] !== '/') {
            configuration.resources.path = configuration.resources.path + '/';
        }
    }

    //
    // Creating the mighty guru object which knows everything.
    //
    var guru = new Guru(configuration);

    //
    // Creating the trainee object which is like a helper for the guru.
    //
    var trainee = new Trainee(configuration);

    //
    // summary:
    //     Inits the view helper.
    //
    // description:
    //     To be able to access the defined i18n resource in
    //     the views, we have to register a dynamic helper. With
    //     this it is possible to access the text resources via
    //     the following directive. Be aware that it depends on
    //     the syntax of the used template engine. So for "jqtpl"
    //     it would look like:
    //
    //         ${lingua.attribute}
    //
    //     # Example #
    //
    //     de-de.json:
    //         {
    //             "title": "Hallo Welt",
    //             "content": {
    //                 "description": "Eine kleine Beschreibung."
    //             }
    //         }
    //
    //     en.json:
    //         {
    //             "title": "Hello World",
    //             "content": {
    //                 "description": "A little description."
    //             }
    //         }
    //
    //     index.html (de-de in the HTTP request header):
    //
${lingua.title}

    //
${lingua.content.description}

    //
    //
    if('function' === typeof app.dynamicHelpers) {
      app.dynamicHelpers({
          lingua: function(req, res){
              return res.lingua.content;
          }
      });
    }
    else if('function' === typeof app.locals.use) {
      app.locals.use(function(req, res) {
        res.locals.lingua = res.lingua.content;
      });
    }

    //
    // DOCME
    //
    app.locals({
        linguac: function(i18n, data) {
            var compile = function(resource, data) {
                if (typeof data === 'object') {
                    for(var param in data) {
                        resource = resource.replace(new RegExp('{'+param+'}','g'), data[param]);
                    }
                } else {
                    resource = resource.replace(/\{(\w*)\}/g, data);
                }

                return resource;
            };

            if (data) {
                i18n = compile(i18n, data);
            }

            return i18n;
        }
    });

    //
    // summary:
    //     The middleware function.
    //
    // description:
    //     This function will be called on every single
    //     HTTP request.
    //
    return function lingua(req, res, next) {
        //
        // Determine the locale in this order:
        // 1. URL query string, 2. Cookie analysis, 3. header analysis
        //
        var locales = trainee.determineLocales(req, res);

        var resource = guru.ask(locales);
        var locale = resource.locale;

        trainee.persistCookie(req, res, locale);

        res.lingua = resource;

        next();
    };
};<commit_msg>Source documentation and merged Express 3.0 compatibility patch.<commit_after>/*
 * express-lingua
 * A i18n middleware for the Express.js framework.
 *
 * Licensed under the MIT:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright (c) 2011, André König (andre.koenig -[at]- gmail [*dot*] com)
 *
 */
var Guru = require('./guru');
var Trainee = require('./trainee');

module.exports = function(app, options) {

    var _name = 'lingua';

    //
    // The lingua configuration object.
    //
    var configuration = {
        storage: {
            key: 'language'
        },
        resources: {
            defaultLocale: options.defaultLocale,
            path: options.path,
            serialisation: '.json'
        }
    };

    //
    // Verify the given parameters.
    //
    // So the middleware init call should look like:
    //
    //     app.configure(function() {
    //         // Lingua configuration
    //         app.use(lingua(app, {
    //             defaultLocale: 'en',
    //             path: __dirname + '/i18n'
    //         }));
    //     });
    //
    // It is necessary to define the "default locale" and the "path"
    // where lingua finds the i18n resource files.
    //
    if (!configuration.resources.defaultLocale) {
        throw new Error(_name + ': Please define a default locale while registering the middleware.');
    }

    if (!configuration.resources.path) {
        throw new Error(_name + ': Please define a path where ' + _name +  ' can find your locales.');
    } else {
        if (configuration.resources.path[configuration.resources.path.length] !== '/') {
            configuration.resources.path = configuration.resources.path + '/';
        }
    }

    //
    // Creating the mighty guru object which knows everything.
    //
    var guru = new Guru(configuration);

    //
    // Creating the trainee object which is like a helper for the guru.
    //
    var trainee = new Trainee(configuration);

    //
    // summary:
    //     Inits the view helper.
    //
    // description:
    //     To be able to access the defined i18n resource in
    //     the views, we have to register a dynamic helper. With
    //     this it is possible to access the text resources via
    //     the following directive. Be aware that it depends on
    //     the syntax of the used template engine. So for "jqtpl"
    //     it would look like:
    //
    //         ${lingua.attribute}
    //
    //     # Example #
    //
    //     de-de.json:
    //         {
    //             "title": "Hallo Welt",
    //             "content": {
    //                 "description": "Eine kleine Beschreibung."
    //             }
    //         }
    //
    //     en.json:
    //         {
    //             "title": "Hello World",
    //             "content": {
    //                 "description": "A little description."
    //             }
    //         }
    //
    //     index.html (de-de in the HTTP request header):
    //
${lingua.title}

    //
${lingua.content.description}

    //
    //
    if('function' === typeof app.dynamicHelpers) {
      app.dynamicHelpers({
          lingua: function(req, res){
              return res.lingua.content;
          }
      });
    }
    else if('function' === typeof app.locals.use) {
      app.locals.use(function(req, res) {
        res.locals.lingua = res.lingua.content;
      });
    }

    //
    // A "compiler" for dynamic data. With "linguac" it is possible
    // to include dynamic data into a text resource.
    //
    app.locals({
        linguac: function(i18n, data) {
            var compile = function(resource, data) {
                if (typeof data === 'object') {
                    for(var param in data) {
                        resource = resource.replace(new RegExp('{'+param+'}','g'), data[param]);
                    }
                } else {
                    resource = resource.replace(/\{(\w*)\}/g, data);
                }

                return resource;
            };

            if (data) {
                i18n = compile(i18n, data);
            }

            return i18n;
        }
    });

    //
    // summary:
    //     The middleware function.
    //
    // description:
    //     This function will be called on every single
    //     HTTP request.
    //
    return function lingua(req, res, next) {
        //
        // Determine the locale in this order:
        // 1. URL query string, 2. Cookie analysis, 3. header analysis
        //
        var locales = trainee.determineLocales(req, res);

        var resource = guru.ask(locales);
        var locale = resource.locale;

        trainee.persistCookie(req, res, locale);

        res.lingua = resource;

        next();
    };
};<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import R from 'ramda';
import { format, getTime } from 'date-fns';

export class Table extends Component {
  render() {
    const repositories = this.props.repositories;
    const cumulatedCountByRepository = this.props.cumulatedCountByRepository;
    return (

            Day
            Total
            {repositories.map(repository => (
              {repository}
            ))}

          {this.props.days.map(day => (

              {format(day, 'MM/DD/YYYY')}

                {R.reduce(
                  (acc, repo) =>
                    acc + (cumulatedCountByRepository[repo][getTime(day)] || 0),
                  0,
                  repositories
                )}

              {repositories.map(repository => (

                  {cumulatedCountByRepository[repository][getTime(day)] || 0}

              ))}

          ))}

    );
  }
}

Table.propTypes = {
  repositories: PropTypes.array.isRequired,
  days: PropTypes.array.isRequired,
  cumulatedCountByRepository: PropTypes.object.isRequired,
};
<commit_msg>Reduce duplication<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';

import R from 'ramda';
import { format, getTime } from 'date-fns';

export class Table extends Component {
  render() {
    const repositories = this.props.repositories;
    const cumulatedCountByRepository = this.props.cumulatedCountByRepository;
    return (

            Day
            Total
            {repositories.map(repository => (
              {repository}
            ))}

          {this.props.days.map(day => {
            const time = getTime(day);
            return (

                {format(day, 'MM/DD/YYYY')}

                  {R.reduce(
                    (acc, repo) =>
                      acc + (cumulatedCountByRepository[repo][time] || 0),
                    0,
                    repositories
                  )}

                {repositories.map(repository => (

                    {cumulatedCountByRepository[repository][time] || 0}

                ))}

            );
          })}

    );
  }
}

Table.propTypes = {
  repositories: PropTypes.array.isRequired,
  days: PropTypes.array.isRequired,
  cumulatedCountByRepository: PropTypes.object.isRequired,
};
<|endoftext|>