<commit_before>/**
 * Copyright 2015 IBM Corp. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var fs             = require('fs');
var url            = require('url');
var extend         = require('extend');
var requestFactory = require('../../lib/requestwrapper');
var solr           = require('solr-client');

function RetrieveAndRank(options) {
  var serviceDefaults = {
    version: 'v1',
    url: 'https://gateway.watsonplatform.net/search/api'
  };

  // Extend default options with user provided options
  this._options = extend(serviceDefaults, options);
}

// Solr cluster lifecycle operations

/**
 * Lists all Solr clusters currently associated with the service instance.
 *
 * @param params An Object representing the parameters for this service call.
 *   This request currently does not require any parameters.
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.listClusters = function(params, callback) {
  return sendRequest('GET', solrClustersPath(), this._options, callback);
};

/**
 * Creates a Solr cluster.
 *
 * @param params An Object representing the parameters for this service call.
 *   Optional params
 *     - cluster_name: name to use for identifying the cluster in responses
 *     - cluster_size: size of the cluster to create
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.createCluster = function(params, callback) {
  // Avoid modifying the global options by making a deep copy
  var createOptions = JSON.parse(JSON.stringify(this._options));
  createOptions.body = JSON.stringify(params || {});
  if (createOptions.headers === undefined) {
    createOptions.headers = {};
  }
  createOptions.headers['Content-Type'] = 'application/json';

  return sendRequest('POST', solrClustersPath(), createOptions, callback);
};

/**
 * Checks whether the specified Solr cluster is ready for use.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to poll
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.pollCluster = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  }
  return sendRequest('GET', solrClusterPath(params.cluster_id), this._options, callback);
};

/**
 * Deletes an existing Solr cluster.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to delete
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.deleteCluster = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  }
  return sendRequest('DELETE', solrClusterPath(params.cluster_id), this._options, callback);
};

// Solr config operations

/**
 * Lists the configuration sets in ZooKeeper.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to get configuration from
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.listConfigs = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  }
  return sendRequest('GET', solrConfigsPath(params.cluster_id), this._options, callback);
};

/**
 * Upload a configuration set to ZooKeeper.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to upload configuration to
 *     - config_name: the name of the config in ZooKeeper referenced when creating a collection
 *     - config_zip_path: the ZIP file to upload
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.uploadConfig = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.config_name) {
    return callback(new Error('Missing required parameter: config_name'));
  } else if (!params.config_zip_path) {
    return callback(new Error('Missing required parameter: config_zip_path'));
  }

  // Avoid modifying the global options by making a deep copy
  var uploadOptions = JSON.parse(JSON.stringify(this._options));
  uploadOptions.body = fs.readFileSync(params.config_zip_path);
  if (uploadOptions.headers === undefined) {
    uploadOptions.headers = {};
  }
  uploadOptions.headers['Content-Type'] = 'application/zip';

  return sendRequest('POST', solrConfigPath(params.cluster_id, params.config_name), uploadOptions, callback);
};

/**
 * Get a configuration set from ZooKeeper as a ZIP file.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to get configuration from
 *     - config_name: the name of the config in ZooKeeper
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.getConfig = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.config_name) {
    return callback(new Error('Missing required parameter: config_name'));
  }
  return sendRequest('GET', solrConfigPath(params.cluster_id, params.config_name), this._options, callback);
};

/**
 * Delete a configuration set in ZooKeeper.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to delete configuration from
 *     - config_name: the name of the config in ZooKeeper
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.deleteConfig = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.config_name) {
    return callback(new Error('Missing required parameter: config_name'));
  }
  return sendRequest('DELETE', solrConfigPath(params.cluster_id, params.config_name), this._options, callback);
};

// Solr collection operations

/**
 * List all collections for a given Solr cluster.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to list collections from
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.listCollections = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  }
  return sendRequest('GET', adminCollectionsPath(params.cluster_id, 'LIST'), this._options, callback);
};

/**
 * Create a Solr collection.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to create the collection on
 *     - collection_name: the name of the collection to create
 *     - config_name: the name of the config in ZooKeeper
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.createCollection = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.collection_name) {
    return callback(new Error('Missing required parameter: collection_name'));
  } else if (!params.config_name) {
    return callback(new Error('Missing required parameter: config_name'));
  }
  var createPath = adminCollectionsPath(params.cluster_id, 'CREATE');
  createPath += '&name=' + params.collection_name + '&collection.configName=' + params.config_name;
  return sendRequest('GET', createPath, this._options, callback);
};

/**
 * Delete a Solr collection.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to delete the collection on
 *     - collection_name: the name of the collection to delete
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.deleteCollection = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.collection_name) {
    return callback(new Error('Missing required parameter: collection_name'));
  }
  var deletePath = adminCollectionsPath(params.cluster_id, 'DELETE') + '&name=' + params.collection_name;
  return sendRequest('GET', deletePath, this._options, callback);
};

/**
 * Get a Solr client for indexing and searching documents.
 * See https://github.com/lbdremy/solr-node-client for documentation and examples.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to delete the collection on
 *     - collection_name: the name of the collection for indexing/searching
 *     - username: the Bluemix service username
 *     - password: the Bluemix service password
 */
RetrieveAndRank.prototype.createSolrClient = function(params) {
  if (!params || !params.cluster_id) {
    throw new Error('Missing required parameter: cluster_id');
  } else if (!params.collection_name) {
    throw new Error('Missing required parameter: collection_name');
  }
  var serviceUrl = url.parse(this._options.url);
  var apiPath = serviceUrl.path === '/' ? '' : serviceUrl.path || '';

  var solrClient = solr.createClient({
    host: serviceUrl.hostname,
    path: apiPath + solrClusterPath(params.cluster_id) + '/solr',
    port: serviceUrl.port || '443',
    secure: true,
    core: params.collection_name
  });
  solrClient.basicAuth(params.username, params.password);
  return solrClient;
};

// Helper methods

function solrClustersPath() {
  return '/v1/solr_clusters';
}

function solrClusterPath(clusterId) {
  return solrClustersPath() +'/' + clusterId;
}

function solrConfigsPath(clusterId) {
  return solrClusterPath(clusterId) + '/config';
}

function solrConfigPath(clusterId, configName) {
  return solrConfigsPath(clusterId) + '/' + configName;
}

function adminCollectionsPath(clusterId, action) {
  return solrClusterPath(clusterId) + '/solr/admin/collections?action=' + action;
}

function sendRequest(method, url, options, callback) {
  var parameters = {
    options: {
      method: method,
      url: url
    },
    defaultOptions: options
  };
  return requestFactory(parameters, callback);
}

module.exports = RetrieveAndRank;
<commit_msg>use api_key to get username and password for retrieve and rank. #111<commit_after>/**
 * Copyright 2015 IBM Corp. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var fs             = require('fs');
var url            = require('url');
var extend         = require('extend');
var requestFactory = require('../../lib/requestwrapper');
var solr           = require('solr-client');

function RetrieveAndRank(options) {
  var serviceDefaults = {
    version: 'v1',
    url: 'https://gateway.watsonplatform.net/search/api'
  };

  // Extend default options with user provided options
  this._options = extend(serviceDefaults, options);
}

// Solr cluster lifecycle operations

/**
 * Lists all Solr clusters currently associated with the service instance.
 *
 * @param params An Object representing the parameters for this service call.
 *   This request currently does not require any parameters.
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.listClusters = function(params, callback) {
  return sendRequest('GET', solrClustersPath(), this._options, callback);
};

/**
 * Creates a Solr cluster.
 *
 * @param params An Object representing the parameters for this service call.
 *   Optional params
 *     - cluster_name: name to use for identifying the cluster in responses
 *     - cluster_size: size of the cluster to create
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.createCluster = function(params, callback) {
  // Avoid modifying the global options by making a deep copy
  var createOptions = JSON.parse(JSON.stringify(this._options));
  createOptions.body = JSON.stringify(params || {});
  if (createOptions.headers === undefined) {
    createOptions.headers = {};
  }
  createOptions.headers['Content-Type'] = 'application/json';

  return sendRequest('POST', solrClustersPath(), createOptions, callback);
};

/**
 * Checks whether the specified Solr cluster is ready for use.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to poll
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.pollCluster = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  }
  return sendRequest('GET', solrClusterPath(params.cluster_id), this._options, callback);
};

/**
 * Deletes an existing Solr cluster.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to delete
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.deleteCluster = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  }
  return sendRequest('DELETE', solrClusterPath(params.cluster_id), this._options, callback);
};

// Solr config operations

/**
 * Lists the configuration sets in ZooKeeper.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to get configuration from
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.listConfigs = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  }
  return sendRequest('GET', solrConfigsPath(params.cluster_id), this._options, callback);
};

/**
 * Upload a configuration set to ZooKeeper.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to upload configuration to
 *     - config_name: the name of the config in ZooKeeper referenced when creating a collection
 *     - config_zip_path: the ZIP file to upload
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.uploadConfig = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.config_name) {
    return callback(new Error('Missing required parameter: config_name'));
  } else if (!params.config_zip_path) {
    return callback(new Error('Missing required parameter: config_zip_path'));
  }

  // Avoid modifying the global options by making a deep copy
  var uploadOptions = JSON.parse(JSON.stringify(this._options));
  uploadOptions.body = fs.readFileSync(params.config_zip_path);
  if (uploadOptions.headers === undefined) {
    uploadOptions.headers = {};
  }
  uploadOptions.headers['Content-Type'] = 'application/zip';

  return sendRequest('POST', solrConfigPath(params.cluster_id, params.config_name), uploadOptions, callback);
};

/**
 * Get a configuration set from ZooKeeper as a ZIP file.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to get configuration from
 *     - config_name: the name of the config in ZooKeeper
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.getConfig = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.config_name) {
    return callback(new Error('Missing required parameter: config_name'));
  }
  return sendRequest('GET', solrConfigPath(params.cluster_id, params.config_name), this._options, callback);
};

/**
 * Delete a configuration set in ZooKeeper.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to delete configuration from
 *     - config_name: the name of the config in ZooKeeper
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.deleteConfig = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.config_name) {
    return callback(new Error('Missing required parameter: config_name'));
  }
  return sendRequest('DELETE', solrConfigPath(params.cluster_id, params.config_name), this._options, callback);
};

// Solr collection operations

/**
 * List all collections for a given Solr cluster.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to list collections from
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.listCollections = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  }
  return sendRequest('GET', adminCollectionsPath(params.cluster_id, 'LIST'), this._options, callback);
};

/**
 * Create a Solr collection.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to create the collection on
 *     - collection_name: the name of the collection to create
 *     - config_name: the name of the config in ZooKeeper
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.createCollection = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.collection_name) {
    return callback(new Error('Missing required parameter: collection_name'));
  } else if (!params.config_name) {
    return callback(new Error('Missing required parameter: config_name'));
  }
  var createPath = adminCollectionsPath(params.cluster_id, 'CREATE');
  createPath += '&name=' + params.collection_name + '&collection.configName=' + params.config_name;
  return sendRequest('GET', createPath, this._options, callback);
};

/**
 * Delete a Solr collection.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to delete the collection on
 *     - collection_name: the name of the collection to delete
 *
 * @param callback The callback.
 */
RetrieveAndRank.prototype.deleteCollection = function(params, callback) {
  if (!params || !params.cluster_id) {
    return callback(new Error('Missing required parameter: cluster_id'));
  } else if (!params.collection_name) {
    return callback(new Error('Missing required parameter: collection_name'));
  }
  var deletePath = adminCollectionsPath(params.cluster_id, 'DELETE') + '&name=' + params.collection_name;
  return sendRequest('GET', deletePath, this._options, callback);
};

/**
 * Get a Solr client for indexing and searching documents.
 * See https://github.com/lbdremy/solr-node-client for documentation and examples.
 *
 * @param params An Object representing the parameters for this service call.
 *   Required params:
 *     - cluster_id: the ID of the Solr cluster to delete the collection on
 *     - collection_name: the name of the collection for indexing/searching
 *     - username: the Bluemix service username
 *     - password: the Bluemix service password
 */
RetrieveAndRank.prototype.createSolrClient = function(params) {
  if (!params || !params.cluster_id) {
    throw new Error('Missing required parameter: cluster_id');
  } else if (!params.collection_name) {
    throw new Error('Missing required parameter: collection_name');
  }
  var serviceUrl = url.parse(this._options.url);
  var apiPath = serviceUrl.path === '/' ? '' : serviceUrl.path || '';

  var solrClient = solr.createClient({
    host: serviceUrl.hostname,
    path: apiPath + solrClusterPath(params.cluster_id) + '/solr',
    port: serviceUrl.port || '443',
    secure: true,
    core: params.collection_name
  });

  if (this._options.api_key) {
    var auth = new Buffer(this._options.api_key, 'base64').toString('ascii').split(':');
    solrClient.basicAuth(auth[0], auth[1]);
  }
  return solrClient;
};

// Helper methods

function solrClustersPath() {
  return '/v1/solr_clusters';
}

function solrClusterPath(clusterId) {
  return solrClustersPath() +'/' + clusterId;
}

function solrConfigsPath(clusterId) {
  return solrClusterPath(clusterId) + '/config';
}

function solrConfigPath(clusterId, configName) {
  return solrConfigsPath(clusterId) + '/' + configName;
}

function adminCollectionsPath(clusterId, action) {
  return solrClusterPath(clusterId) + '/solr/admin/collections?action=' + action;
}

function sendRequest(method, url, options, callback) {
  var parameters = {
    options: {
      method: method,
      url: url
    },
    defaultOptions: options
  };
  return requestFactory(parameters, callback);
}

module.exports = RetrieveAndRank;
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////////////////
// Very simple Lisp on Javascript system
// Author: Francisco Soto <ebobby@ebobby.org>
////////////////////////////////////////////////////////////////////////////////////////////
var Lisp = (function () {
    // This is what a cons cell is like.
    function _cell (car, cdr) {
        this.car = car;
        this.cdr = cdr;
    }

    // js lisp read, transforms arrays to cons cells.
    function read (exp) {
        if (Array.isArray(exp)) {
            if (exp.length == 0) {
                return null;
            }

            return cons(read(exp[0]), read(exp.slice(1)));
        }
        else {
            return exp;
        }
    }

    // js lisp print, transforms cons cells into arrays and rely on js printer.
    function print (sexp, acc) {
        if (sexp === null) {
            if (acc) {
                return acc;
            }

            return null;
        }

        if (atom(sexp)) {
            if (acc) {
                acc.push(".");
                acc.push(sexp);
                return acc;
            }

            return sexp;
        }
        else {
            if (acc) {
                acc.push(print(car(sexp)));
                return print(cdr(sexp), acc);
            }

            return print(cdr(sexp), [ print(car(sexp)) ] );
        }
    }

    // evaluate lisp expressions
    function eval (sexp) {
        // evaluate the conditions lists for "cond".
        function eval_conditions(conditions) {
            if (conditions === null) {
                return null;
            }

            if (eval(car(car(conditions)))) {
                return eval(car(cdr(car(conditions))));
            }
            else {
                return eval_conditions(cdr(conditions));
            }
        }

        if (atom(sexp)) {
            return sexp;
        }

        if (atom(car(sexp))) {
            if (eq(car(sexp), "quote")) { return car(cdr(sexp)); }
            if (eq(car(sexp), "cond"))  { return eval_conditions(cdr(sexp)); }
            if (eq(car(sexp), "atom"))  { return atom(eval(car(cdr(sexp)))); }
            if (eq(car(sexp), "eq"))    { return eq(eval(car(cdr(sexp))), eval(car(cdr(cdr(sexp))))); }
            if (eq(car(sexp), "car"))   { return car(eval(car(cdr(sexp)))); }
            if (eq(car(sexp), "cdr"))   { return cdr(eval(car(cdr(sexp)))); }
            if (eq(car(sexp), "cons"))  { return cons(eval(car(cdr(sexp))), eval(car(cdr(cdr(sexp))))); }
        }

        throw "Can't evaluate.";
    }

    ////////////////////////////////////////////////////////////////////////////////
    // Base Lisp functions
    ////////////////////////////////////////////////////////////////////////////////
    function cons (car, cdr) {
        return new _cell(car, cdr);
    }

    function car (obj) {
        return obj.car;
    }

    function cdr (obj) {
        return obj.cdr;
    }

    function atom (exp) {
        return !(exp instanceof _cell);
    }

    function eq (obj1, obj2) {
        return obj1 === obj2;
    }

    // The system public interface.
    return {
        eval: function (exp) {
            return print(eval(read(exp)));
        }
    }
})();
<commit_msg>Added the progn special form.<commit_after>////////////////////////////////////////////////////////////////////////////////////////////
// Very simple Lisp on Javascript system
// Author: Francisco Soto <ebobby@ebobby.org>
////////////////////////////////////////////////////////////////////////////////////////////
var Lisp = (function () {
    // This is what a cons cell is like.
    function _cell (car, cdr) {
        this.car = car;
        this.cdr = cdr;
    }

    // js lisp read, transforms arrays to cons cells.
    function read (exp) {
        if (Array.isArray(exp)) {
            if (exp.length == 0) {
                return null;
            }

            return cons(read(exp[0]), read(exp.slice(1)));
        }
        else {
            return exp;
        }
    }

    // js lisp print, transforms cons cells into arrays and rely on js printer.
    function print (sexp, acc) {
        if (sexp === null) {
            if (acc) {
                return acc;
            }

            return null;
        }

        if (atom(sexp)) {
            if (acc) {
                acc.push(".");
                acc.push(sexp);
                return acc;
            }

            return sexp;
        }
        else {
            if (acc) {
                acc.push(print(car(sexp)));
                return print(cdr(sexp), acc);
            }

            return print(cdr(sexp), [ print(car(sexp)) ] );
        }
    }

    // evaluate lisp expressions
    function eval (sexp) {

        if (atom(sexp)) {
            return sexp;
        }

        if (atom(car(sexp))) {
            // Function calls
            if (eq(car(sexp), "atom"))   { return atom(eval(car(cdr(sexp)))); }
            if (eq(car(sexp), "eq"))     { return eq(eval(car(cdr(sexp))), eval(car(cdr(cdr(sexp))))); }
            if (eq(car(sexp), "car"))    { return car(eval(car(cdr(sexp)))); }
            if (eq(car(sexp), "cdr"))    { return cdr(eval(car(cdr(sexp)))); }
            if (eq(car(sexp), "cons"))   { return cons(eval(car(cdr(sexp))), eval(car(cdr(cdr(sexp))))); }

            // Special forms
            if (eq(car(sexp), "progn"))  { return eval_progn(cdr(sexp)); }
            if (eq(car(sexp), "quote"))  { return car(cdr(sexp)); }
            if (eq(car(sexp), "cond"))   { return eval_conditions(cdr(sexp)); }
        }

        throw "Can't evaluate.";
    }

    // evaluate the conditions lists for "cond".
    function eval_conditions(conditions) {
        if (conditions === null) {
            return null;
        }

        if (eval(car(car(conditions)))) {
            return eval(car(cdr(car(conditions))));
        }
        else {
            return eval_conditions(cdr(conditions));
        }
    }

    function eval_progn(forms, last) {
        if (forms === null) {
            return last;
        }
        else {
            return eval_progn(cdr(forms), eval(car(forms)));
        }
    }

    ////////////////////////////////////////////////////////////////////////////////
    // Base Lisp functions
    ////////////////////////////////////////////////////////////////////////////////
    function cons (car, cdr) {
        return new _cell(car, cdr);
    }

    function car (obj) {
        return obj.car;
    }

    function cdr (obj) {
        return obj.cdr;
    }

    function atom (exp) {
        return !(exp instanceof _cell);
    }

    function eq (obj1, obj2) {
        return obj1 === obj2;
    }

    // The system public interface.
    return {
        eval: function (exp) {
            return print(eval(read(exp)));
        }
    }
})();
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';

foam.CLASS({
  package: 'org.chromium.webidl',
  name: 'FetchSpecRunner',
  extends: 'org.chromium.webidl.PipelineRunner',

  requires: ['org.chromium.webidl.HTMLFileContents'],

  constants: {
    MISSING_URLS: 'URL property of PipelineMessage is missing!',
  },

  methods: [
    function run(message) {
      var sup = this.SUPER(message);

      // If SUPER threw an error, then we are done.
      if (sup) return;

      var urls = message.urls;
      if (!urls)
        return this.error(this.fmtErrorMsg(this.MISSING_URLS));

      // TODO: Replace Node Clusters with Dedicated worker using FOAM Registries.
      var cluster = require('cluster');
      var path = require('path');

      // Instantiating Node instance to handle HTTP Fetching.
      cluster.setupMaster({
        silent: true,
        exec: path.resolve(__dirname, './fetchWorkerScript.js'),
      });
      var worker = cluster.fork();

      worker.on('online', function() {
        worker.send(urls);
      });

      worker.on('message', function(data) {
        if (typeof data !== 'object')
          return this.error(this.fmtErrorMsg(data));

        var htmlFile = this.HTMLFileContents.create(data);
        var newMessage = this.PipelineMessage.create({
          htmlFile: htmlFile,
          parser: message.parser,
          renderer: `${message.renderer}-WebSpec`,
        });
        this.output(newMessage);
      }.bind(this));
    },
  ]
});
<commit_msg>Adding documentation for FetchSpecRunner<commit_after>// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';

foam.CLASS({
  package: 'org.chromium.webidl',
  name: 'FetchSpecRunner',
  extends: 'org.chromium.webidl.PipelineRunner',

  requires: ['org.chromium.webidl.HTMLFileContents'],

  documentation: `A runnable box that expects to receive a PipelineMessage
    containing an array of URLs. The component will spawn a HTTP worker,
    which fetches the pages at the given URLs.`,

  constants: {
    MISSING_URLS: 'URL property of PipelineMessage is missing!',
  },

  methods: [
    function run(message) {
      var sup = this.SUPER(message);

      // If SUPER threw an error, then we are done.
      if (sup) return;

      var urls = message.urls;
      if (!urls)
        return this.error(this.fmtErrorMsg(this.MISSING_URLS));

      // TODO: Replace Node Clusters with Dedicated worker using FOAM Registries.
      var cluster = require('cluster');
      var path = require('path');

      // Instantiating Node instance to handle HTTP Fetching.
      cluster.setupMaster({
        silent: true,
        exec: path.resolve(__dirname, './fetchWorkerScript.js'),
      });
      var worker = cluster.fork();

      worker.on('online', function() {
        worker.send(urls);
      });

      worker.on('message', function(data) {
        if (typeof data !== 'object')
          return this.error(this.fmtErrorMsg(data));

        var htmlFile = this.HTMLFileContents.create(data);
        var newMessage = this.PipelineMessage.create({
          htmlFile: htmlFile,
          parser: message.parser,
          renderer: `${message.renderer}-WebSpec`,
        });
        this.output(newMessage);
      }.bind(this));
    },
  ]
});
<|endoftext|>


<commit_before>var md5 = require('md5');

/*
 * JavaScript utilities.
 */
export default class Utils {
    /*
     * Formats a Date() object into a string.
     */
    static formatDateTime(date) {
        return moment(date).format('LLLL');
    }

    /*
     * Returns a Date() object from a string in the same format
     * as formatDateTime();
     */
    static dateFromString(dateTimeString) {
        if (typeof dateTimeString === 'object') {
            // Assume that dateTimeString is a Date() object
            // and reurn that.
            return dateTimeString;
        }

        return new Date(dateTimeString.replace(' ', 'T').replace('Z', ''));
    }

    /*
     * Get the Rails authenticity token.
     */
    static getAuthenticityToken() {
        return document.querySelector('meta[name=csrf-token').getAttribute('content');
    }

    static getGravatarUrl(email) {
        var hashedEmail = md5(email.trim().toLowerCase());
        return `https://www.gravatar.com/avatar/${hashedEmail}.jpg?s=32&d=mm`;
    }
}<commit_msg>Fix multiple JavaScript functions not working in Safari.<commit_after>var md5 = require('md5');

/*
 * JavaScript utilities.
 */
export default class Utils {
    /*
     * Formats a Date() object into a string.
     */
    static formatDateTime(date) {
        return moment(date).format('LLLL');
    }

    /*
     * Returns a Date() object from a string in the same format
     * as formatDateTime();
     */
    static dateFromString(dateTimeString) {
        if (typeof dateTimeString === 'object') {
            // Assume that dateTimeString is a Date() object
            // and reurn that.
            return dateTimeString;
        }

        return new Date(dateTimeString.replace(' ', 'T').replace('Z', ''));
    }

    /*
     * Get the Rails authenticity token.
     */
    static getAuthenticityToken() {
        return document.querySelector('meta[name=csrf-token]')
            .getAttribute('content');
    }

    static getGravatarUrl(email) {
        var hashedEmail = md5(email.trim().toLowerCase());
        return `https://www.gravatar.com/avatar/${hashedEmail}.jpg?s=32&d=mm`;
    }
}<|endoftext|>


<commit_before>var http = require('http');
var url = process.argv[2];
http.get(url, function callback(response){
	response.setEncoding('utf8');
	response.on('data', function(data){
		console.log(data);

	})
});
<commit_msg>Delete vk6 - same as vk7!<commit_after><|endoftext|>


<commit_before>import * as ActionTypes from '../actions'
import merge from 'lodash/merge'
import union from 'lodash/union'
import uniq from 'lodash/uniq'
import moment from 'moment'

export const metadataReducer = (state = {}, action) => {
  let copyState

  if (action.response) {
    switch (action.type) {
      case ActionTypes.COUNT_SUCCESS:
      case ActionTypes.METADATA_SUCCESS:
      case ActionTypes.MIGRATION_SUCCESS:
      case ActionTypes.RELATEDDATASET_SUCCESS:
        let merged = merge({}, state, action.response)
        return Object.assign({}, state, merged)
      case ActionTypes.COLPROPS_SUCCESS:
        if (ActionTypes.COLPROPS_SUCCESS) {
          action.response.categoryColumns = union([], state.categoryColumns, action.response.categoryColumns)
        }
        return merge({}, state, action.response)
      // remove - move to table and chart objects
      case ActionTypes.DATA_SUCCESS:
        let merged2 = merge({}, state, action.response)
        if (action.response.query) {
          merged2.query.data = action.response.query.data
        } else {
          merged2.table.data = action.response.table.data
        }
        return Object.assign({}, state, merged2)
      default:
        return state
    }
  }

  switch (action.type) {
    case ActionTypes.LOAD_TABLE:
      return merge({}, state, {
        table: {
          tablePage: 0,
          isFetching: true
        }
      })
    case ActionTypes.UPDATE_PAGE:
      return merge({}, state, {
        table: {
          tablePage: action.page
        }
      })
    case ActionTypes.METADATA_REQUEST:
      let freshState = {
        query: {
          isFetching: true,
          dateBy: 'year'
        },
        columns: {}
      }
      return merge({}, freshState)
    // move to table
    case ActionTypes.SORT_COLUMN:
      let updatedState = {
        table: {
          sorted: state.table.sorted ? uniq([action.key].concat(state.table.sorted)) : [action.key]
        },
        columns: {
          [action.key]: {
            sortDir: action.dir
          }
        }
      }
      return merge({}, state, updatedState)
    case ActionTypes.SELECT_COLUMN:
      let updatedQuery = {
        query: {
          isFetching: true,
          selectedColumn: action.payload
        }
      }
      if (state.query.groupBy === action.column) {
        updatedQuery.query.groupBy = null
      }
      return merge({}, state, updatedQuery)
    case ActionTypes.GROUP_BY:
      let groupKey = action.payload ? action.payload.value : null
      return merge({}, state, {
        query: {
          groupBy: groupKey
        }
      })
    case ActionTypes.SUM_BY:
      let sumKey = action.payload ? action.payload.value : null
      return merge({}, state, {
        query: {
          sumBy: sumKey
        }
      })
    case ActionTypes.CHANGE_DATEBY:
      return merge({}, state, {
        query: {
          dateBy: action.payload
        }
      })
    case ActionTypes.ADD_FILTER:
      return merge({}, state, {
        query: {
          filters: {
            [action.payload.value]: {}
          }
        }
      })
    case ActionTypes.APPLY_CHART_TYPE:
      return merge({}, state, {
        query: {
          chartType: action.chartType
        }
      })
    case ActionTypes.REMOVE_FILTER:
      copyState = {...state}
      delete copyState.query.filters[action.payload]
      return merge({}, state, copyState)
    case ActionTypes.UPDATE_FILTER:
      let newOptions = action.payload.options
      copyState = Object.assign({}, state)
      let existingOptions = copyState.query.filters[action.payload.key].options || ''
      let isSelected = (newOptions.selected)
      let newState

      if (isSelected && Array.isArray(existingOptions.selected) &&
        (existingOptions.selected.length !== newOptions.selected.length || typeof newOptions.selected === 'string')) {
        copyState.query.filters[action.payload.key].options.selected = action.payload.options.selected
        newState = merge({}, copyState)
      } else {
        let updatedOptions = {
          query: {
            filters: {
              [action.payload.key]: {
                options: action.payload.options
              }
            }
          }
        }
        newState = merge({}, state, updatedOptions)
      }
      return newState
    default:
      return state

  }
}

function makePercent (item) {
  let prcnt =parseFloat(item) * 100
  return String(prcnt.toFixed(2)) + "%"
}
export const makeDatasetFactDict = (state) => {
  const propsToKeep = {'rowCount': 'Number of Rows',
                        'rowLabel': 'Row Label',
                        'rowIdentifier': 'Row Identifier',
                        'documented_percentage': 'Percent of Fields Documented',
                        'dupe_record_percent': 'Duplicate Record Percent',
                        'category': 'Category',
                        'keywords': 'Tags'
                      }
  let datasetFacts = []
  Object.keys(propsToKeep).forEach(function (key) {
      if ((state.metadata[key]) && (typeof state.metadata[key] !== 'undefined')) {
        let value = state.metadata[key]
        if (key === 'documented_percentage' || key === 'dupe_record_percent') {
          value = makePercent(state.metadata[key])
        }
        if(key === 'keywords'){
          let tags = value.split(",")
          value = tags.join(", ")
        }
        datasetFacts.push({'header': propsToKeep[key], 'value': value})
      }
  })
  return datasetFacts
}

export const makeColTypesCnt = (state) => {
  const colTypesCnt = {
    'field_count': 'Field Count',
    'text_count': 'Text Field Count',
    'numeric_count': 'Number Field Count',
    'boolean_count': 'True/False Field Count',
    'timestamp_count': 'Timestamp Field Count',
    'time_count': 'Time Field Count',
    'blob_count': 'Blob Field Count',
    'point_count': 'Geometry: Point Field Count',
    'line_count': 'Geometry: Line Field Count',
    'polygon_count': 'Geometry: Polygon Field Count',
    'multipoint_count': 'Geometry: Multipoint Field Count',
    'multiline_count': 'Geometry: Multiline Field Count',
    'multipolygon_count': 'Geometry: Multipolygon Field Count'
  }
  let colCounts = []
  Object.keys(colTypesCnt).forEach(function (key) {
      if ((state.metadata[key]) && (typeof state.metadata[key] !== 'undefined')) {
        if( parseInt(state.metadata[key], 10) !== 0){
          colCounts.push({'header': colTypesCnt[key], 'value': state.metadata[key]})
        }
      }
  })
  return colCounts
}

export const calculatePublishingHealth = (state) => {
  let pubFreq =  state.metadata.publishingFrequency
  let dayslastUpdt = state.metadata.days_since_last_updated
  const healthThresholds = {
    'Streaming': [2,7],
    'Daily' : [2,7],
    'Weekly': [7,21],
    'Monthly': [32, 90],
    'Bi-annually': [60, 180],
    'Annually': [365,500],
    'Quarterly': [90, 270]
  }
  if (Object.keys(healthThresholds).includes(pubFreq)) {
    let timeIntervals = healthThresholds[pubFreq]
    if (parseInt(dayslastUpdt, 10) <= timeIntervals[0]) {
      return {'value': 'On Time', 'className': 'healthy'}
    } else if ((parseInt(dayslastUpdt, 10) > timeIntervals[0]) && (parseInt(dayslastUpdt, 10) <= timeIntervals[1])) {
      return {'value': 'Delayed', 'className': 'delayed'}
    } else if (parseInt(dayslastUpdt, 10) > timeIntervals[1]) {
      return {'value': 'Stale', 'className': 'stale'}
    }
  }
  return {'value': 'On Time', 'className': 'healthy'}
}

function parseDt(dt){
  dt =  dt.split("T")
  return dt[0]
}

export const makePublishingFacts = (state) => {
  const pubFieldDetails = {
    'days_since_last_updated':'Last Updated',
    'publishingFrequency': 'Publishing Frequency',
    'dataChangeFrequency': 'Data Change Frequency' ,
    'createdAt': 'Dataset Creation Date',
    'days_since_first_created': 'Dataset Age',
  }
  let publishingFaqs = []
  Object.keys(pubFieldDetails).forEach(function (key) {
    if ((state.metadata[key]) && (typeof state.metadata[key] !== 'undefined')) {
      let value = state.metadata[key]
      if (key === 'createdAt') {
        value = parseDt(value)
      }
      else if(key === 'days_since_first_created') {
        value = moment(state.metadata['createdAt']).fromNow()
        value = value.split('ago')
        value = value[0] + ' old'
      }
      else if(key === 'days_since_last_updated') {
        value = moment(state.metadata['rowsUpdatedAt']).fromNow()
      }
      publishingFaqs.push({'header': pubFieldDetails[key], 'value': value})
    }
  })
  return publishingFaqs
}
<commit_msg>removes dataset age from the dataset overview<commit_after>import * as ActionTypes from '../actions'
import merge from 'lodash/merge'
import union from 'lodash/union'
import uniq from 'lodash/uniq'
import moment from 'moment'

export const metadataReducer = (state = {}, action) => {
  let copyState

  if (action.response) {
    switch (action.type) {
      case ActionTypes.COUNT_SUCCESS:
      case ActionTypes.METADATA_SUCCESS:
      case ActionTypes.MIGRATION_SUCCESS:
      case ActionTypes.RELATEDDATASET_SUCCESS:
        let merged = merge({}, state, action.response)
        return Object.assign({}, state, merged)
      case ActionTypes.COLPROPS_SUCCESS:
        if (ActionTypes.COLPROPS_SUCCESS) {
          action.response.categoryColumns = union([], state.categoryColumns, action.response.categoryColumns)
        }
        return merge({}, state, action.response)
      // remove - move to table and chart objects
      case ActionTypes.DATA_SUCCESS:
        let merged2 = merge({}, state, action.response)
        if (action.response.query) {
          merged2.query.data = action.response.query.data
        } else {
          merged2.table.data = action.response.table.data
        }
        return Object.assign({}, state, merged2)
      default:
        return state
    }
  }

  switch (action.type) {
    case ActionTypes.LOAD_TABLE:
      return merge({}, state, {
        table: {
          tablePage: 0,
          isFetching: true
        }
      })
    case ActionTypes.UPDATE_PAGE:
      return merge({}, state, {
        table: {
          tablePage: action.page
        }
      })
    case ActionTypes.METADATA_REQUEST:
      let freshState = {
        query: {
          isFetching: true,
          dateBy: 'year'
        },
        columns: {}
      }
      return merge({}, freshState)
    // move to table
    case ActionTypes.SORT_COLUMN:
      let updatedState = {
        table: {
          sorted: state.table.sorted ? uniq([action.key].concat(state.table.sorted)) : [action.key]
        },
        columns: {
          [action.key]: {
            sortDir: action.dir
          }
        }
      }
      return merge({}, state, updatedState)
    case ActionTypes.SELECT_COLUMN:
      let updatedQuery = {
        query: {
          isFetching: true,
          selectedColumn: action.payload
        }
      }
      if (state.query.groupBy === action.column) {
        updatedQuery.query.groupBy = null
      }
      return merge({}, state, updatedQuery)
    case ActionTypes.GROUP_BY:
      let groupKey = action.payload ? action.payload.value : null
      return merge({}, state, {
        query: {
          groupBy: groupKey
        }
      })
    case ActionTypes.SUM_BY:
      let sumKey = action.payload ? action.payload.value : null
      return merge({}, state, {
        query: {
          sumBy: sumKey
        }
      })
    case ActionTypes.CHANGE_DATEBY:
      return merge({}, state, {
        query: {
          dateBy: action.payload
        }
      })
    case ActionTypes.ADD_FILTER:
      return merge({}, state, {
        query: {
          filters: {
            [action.payload.value]: {}
          }
        }
      })
    case ActionTypes.APPLY_CHART_TYPE:
      return merge({}, state, {
        query: {
          chartType: action.chartType
        }
      })
    case ActionTypes.REMOVE_FILTER:
      copyState = {...state}
      delete copyState.query.filters[action.payload]
      return merge({}, state, copyState)
    case ActionTypes.UPDATE_FILTER:
      let newOptions = action.payload.options
      copyState = Object.assign({}, state)
      let existingOptions = copyState.query.filters[action.payload.key].options || ''
      let isSelected = (newOptions.selected)
      let newState

      if (isSelected && Array.isArray(existingOptions.selected) &&
        (existingOptions.selected.length !== newOptions.selected.length || typeof newOptions.selected === 'string')) {
        copyState.query.filters[action.payload.key].options.selected = action.payload.options.selected
        newState = merge({}, copyState)
      } else {
        let updatedOptions = {
          query: {
            filters: {
              [action.payload.key]: {
                options: action.payload.options
              }
            }
          }
        }
        newState = merge({}, state, updatedOptions)
      }
      return newState
    default:
      return state

  }
}

function makePercent (item) {
  let prcnt =parseFloat(item) * 100
  return String(prcnt.toFixed(2)) + "%"
}
export const makeDatasetFactDict = (state) => {
  const propsToKeep = {'rowCount': 'Number of Rows',
                        'rowLabel': 'Row Label',
                        'rowIdentifier': 'Row Identifier',
                        'documented_percentage': 'Percent of Fields Documented',
                        'dupe_record_percent': 'Duplicate Record Percent',
                        'category': 'Category',
                        'keywords': 'Tags'
                      }
  let datasetFacts = []
  Object.keys(propsToKeep).forEach(function (key) {
      if ((state.metadata[key]) && (typeof state.metadata[key] !== 'undefined')) {
        let value = state.metadata[key]
        if (key === 'documented_percentage' || key === 'dupe_record_percent') {
          value = makePercent(state.metadata[key])
        }
        if(key === 'keywords'){
          let tags = value.split(",")
          value = tags.join(", ")
        }
        datasetFacts.push({'header': propsToKeep[key], 'value': value})
      }
  })
  return datasetFacts
}

export const makeColTypesCnt = (state) => {
  const colTypesCnt = {
    'field_count': 'Field Count',
    'text_count': 'Text Field Count',
    'numeric_count': 'Number Field Count',
    'boolean_count': 'True/False Field Count',
    'timestamp_count': 'Timestamp Field Count',
    'time_count': 'Time Field Count',
    'blob_count': 'Blob Field Count',
    'point_count': 'Geometry: Point Field Count',
    'line_count': 'Geometry: Line Field Count',
    'polygon_count': 'Geometry: Polygon Field Count',
    'multipoint_count': 'Geometry: Multipoint Field Count',
    'multiline_count': 'Geometry: Multiline Field Count',
    'multipolygon_count': 'Geometry: Multipolygon Field Count'
  }
  let colCounts = []
  Object.keys(colTypesCnt).forEach(function (key) {
      if ((state.metadata[key]) && (typeof state.metadata[key] !== 'undefined')) {
        if( parseInt(state.metadata[key], 10) !== 0){
          colCounts.push({'header': colTypesCnt[key], 'value': state.metadata[key]})
        }
      }
  })
  return colCounts
}

export const calculatePublishingHealth = (state) => {
  let pubFreq =  state.metadata.publishingFrequency
  let dayslastUpdt = state.metadata.days_since_last_updated
  const healthThresholds = {
    'Streaming': [2,7],
    'Daily' : [2,7],
    'Weekly': [7,21],
    'Monthly': [32, 90],
    'Bi-annually': [60, 180],
    'Annually': [365,500],
    'Quarterly': [90, 270]
  }
  if (Object.keys(healthThresholds).includes(pubFreq)) {
    let timeIntervals = healthThresholds[pubFreq]
    if (parseInt(dayslastUpdt, 10) <= timeIntervals[0]) {
      return {'value': 'On Time', 'className': 'healthy'}
    } else if ((parseInt(dayslastUpdt, 10) > timeIntervals[0]) && (parseInt(dayslastUpdt, 10) <= timeIntervals[1])) {
      return {'value': 'Delayed', 'className': 'delayed'}
    } else if (parseInt(dayslastUpdt, 10) > timeIntervals[1]) {
      return {'value': 'Stale', 'className': 'stale'}
    }
  }
  return {'value': 'On Time', 'className': 'healthy'}
}

function parseDt(dt){
  dt =  dt.split("T")
  return dt[0]
}

export const makePublishingFacts = (state) => {
  const pubFieldDetails = {
    'days_since_last_updated':'Last Updated',
    'publishingFrequency': 'Publishing Frequency',
    'dataChangeFrequency': 'Data Change Frequency' ,
    'createdAt': 'Dataset Creation Date',
    // 'days_since_first_created': 'Dataset Age',
  }
  let publishingFaqs = []
  Object.keys(pubFieldDetails).forEach(function (key) {
    if ((state.metadata[key]) && (typeof state.metadata[key] !== 'undefined')) {
      let value = state.metadata[key]
      if (key === 'createdAt') {
        value = parseDt(value)
      }
      else if(key === 'days_since_first_created') {
        value = moment(state.metadata['createdAt']).fromNow()
        value = value.split('ago')
        value = value[0] + ' old'
      }
      else if(key === 'days_since_last_updated') {
        value = moment(state.metadata['rowsUpdatedAt']).fromNow()
      }
      publishingFaqs.push({'header': pubFieldDetails[key], 'value': value})
    }
  })
  return publishingFaqs
}
<|endoftext|>


<commit_before>export const statsLatestDecoder = (bands) => {
  // TODO: What if we don't have bands? or max / histogram is not present?
  // i would recommend this service to simply return "null" if something is not formatted as we expect it to be
  const { max, histogram } = bands[0];

  // high confidence alerts from top-level max
  // max = abbbb where a = confidence value, bbbb = days since 2014-12-31
  const encodedMax = max.toString(10);
  const daysSinceString = encodedMax.substring(1, encodedMax.length);

  const daysSince = parseInt(daysSinceString, 10);

  // low confidence alerts from histogram
  // need to find the last non-zero bin where where index < 30,000 (high conf)
  const binSize = (histogram.max - histogram.min) / histogram.bin_count;

  const maxBinIndex = Math.floor((30000 - histogram.min) / binSize);

  const valueBins = histogram.value_count.slice(0, maxBinIndex).reverse();

  // TODO: make sure we get a index here, and not -1, if we get -1 we should exit with "null"
  const latestIndex = valueBins.findIndex((el) => el !== 0);

  // Start of bin represents the encoded value
  const binStart = parseInt(
    histogram.min + (maxBinIndex - latestIndex) * binSize,
    10
  );

  const encodedMaxLowConfidence = binStart.toString(10);
  const daysSinceStringLowConfidence = encodedMaxLowConfidence.substring(
    1,
    encodedMaxLowConfidence.length
  );

  const daysSinceLowConfidence = parseInt(daysSinceStringLowConfidence, 10);

  // NOTE: Removed the ternary here to make it more clear what the end result of this factory is, and what its returning by default

  // OLD:
  // const days =
  // daysSinceLowConfidence > daysSince ? daysSinceLowConfidence : daysSince;

  // whichever is latest (i.e. most days since 2014-12-31)
  if (daysSinceLowConfidence > daysSince) {
    return daysSinceLowConfidence;
  }

  return daysSince;
};
<commit_msg>Adds Math.max<commit_after>export const statsLatestDecoder = (bands) => {
  // TODO: What if we don't have bands? or max / histogram is not present?
  // i would recommend this service to simply return "null" if something is not formatted as we expect it to be
  const { max, histogram } = bands[0];

  // high confidence alerts from top-level max
  // max = abbbb where a = confidence value, bbbb = days since 2014-12-31
  const encodedMax = max.toString(10);
  const daysSinceString = encodedMax.substring(1, encodedMax.length);

  // This is always a confirmed alert
  const daysSince = parseInt(daysSinceString, 10);

  // low confidence alerts from histogram
  // need to find the last non-zero bin where where index < 30,000 (high conf)
  const binSize = (histogram.max - histogram.min) / histogram.bin_count;

  const maxBinIndex = Math.floor((30000 - histogram.min) / binSize);

  const valueBins = histogram.value_count.slice(0, maxBinIndex).reverse();

  // TODO: make sure we get a index here, and not -1, if we get -1 we should exit with "null"
  const latestIndex = valueBins.findIndex((el) => el !== 0);

  // Start of bin represents the encoded value
  const binStart = parseInt(
    histogram.min + (maxBinIndex - latestIndex) * binSize,
    10
  );

  const encodedMaxLowConfidence = binStart.toString(10);
  const daysSinceStringLowConfidence = encodedMaxLowConfidence.substring(
    1,
    encodedMaxLowConfidence.length
  );

  const daysSinceLowConfidence = parseInt(daysSinceStringLowConfidence, 10);

  // NOTE: Removed the ternary here to make it more clear what the end result of this factory is, and what its returning by default

  // OLD:
  // const days =
  // daysSinceLowConfidence > daysSince ? daysSinceLowConfidence : daysSince;

  // whichever is latest (i.e. most days since 2014-12-31)
  // if both are > days since
  const daysSinceArray = [daysSince, daysSinceLowConfidence];

  return Math.max(...daysSinceArray);
};
<|endoftext|>


<commit_before>'use strict';

const { Pattern } = require('hexo-util');
const _ = require('lodash');

function i18nLocalsFilter(locals) {
  const { i18n } = this.theme;
  const { config } = this;
  const i18nDir = config.i18n_dir;
  const { page } = locals;
  let lang = page.lang || page.language;
  const i18nLanguages = i18n.list();
  const i18nConfigLanguages = i18n.languages;

  if (!lang) {
    const pattern = new Pattern(`${i18nDir}/*path`);
    const data = pattern.match(locals.path);

    if (data && data.lang && i18nLanguages.includes(data.lang)) {
      lang = data.lang;
      page.canonical_path = data.path;
    } else {
      // i18n.languages is always an array with at least one argument ('default')
      lang = i18nConfigLanguages[0];
    }

    page.lang = lang;
  }

  page.canonical_path = page.canonical_path || locals.path;

  const languages = _([].concat(lang, i18nConfigLanguages, i18nLanguages)).compact().uniq().value();

  locals.__ = i18n.__(languages);
  locals._p = i18n._p(languages);
}

module.exports = i18nLocalsFilter;
<commit_msg>refactor: drop lodash for i18n filter (#3810)<commit_after>'use strict';

const { Pattern } = require('hexo-util');

function i18nLocalsFilter(locals) {
  const { i18n } = this.theme;
  const { config } = this;
  const i18nDir = config.i18n_dir;
  const { page } = locals;
  let lang = page.lang || page.language;
  const i18nLanguages = i18n.list();
  const i18nConfigLanguages = i18n.languages;

  if (!lang) {
    const pattern = new Pattern(`${i18nDir}/*path`);
    const data = pattern.match(locals.path);

    if (data && data.lang && i18nLanguages.includes(data.lang)) {
      lang = data.lang;
      page.canonical_path = data.path;
    } else {
      // i18n.languages is always an array with at least one argument ('default')
      lang = i18nConfigLanguages[0];
    }

    page.lang = lang;
  }

  page.canonical_path = page.canonical_path || locals.path;

  const languages = [...new Set([].concat(lang, i18nConfigLanguages, i18nLanguages).filter(Boolean))];

  locals.__ = i18n.__(languages);
  locals._p = i18n._p(languages);
}

module.exports = i18nLocalsFilter;
<|endoftext|>


<commit_before>var remote = require('electron').remote;
var app = remote.app;
var dialog = remote.dialog;
var clipboard = remote.clipboard;
var exec = require('child_process').exec;
var fs = require('fs');
var os = require('os');
var path = require('path');
var Jimp = require('jimp');

$(function() {
    var imageURL = decodeURIComponent(window.location.href.split('?lastURL=')[1]);
    var platform = os.platform();
    var isVector = false;

    $('.img').attr('src', imageURL);

    $('.save').on('click', function() {
        if (isVector) {
            var savePath = dialog.showSaveDialog({
                filters: [
                    {name: 'Images', extensions: ['svg']}
                ]
            });

            if (savePath) {
                fs.writeFileSync(savePath, fs.readFileSync(path.join(app.getPath('temp'), 'potrace.svg')));
            }
        } else {
            // save canvas as png
        }
    });

    $('.vector').on('click', function() {

        Jimp.read(imageURL, function(error, image) {
            if (error) return;

            var imgPath = path.join(app.getPath('temp'), 'potrace.bmp');
            var binPath;
            if (platform == 'darwin') {
                binPath = path.join(app.getAppPath(), 'bin', 'osx', 'potrace');
            } else if (platform == 'win32') {
                binPath = path.join(app.getAppPath(), 'bin', 'win', 'potrace.exe');
            } else {
                return;
            }

            image.write(imgPath, function() {
                exec(binPath + ' -s -n ' + imgPath, function(error, stdout) {
                    if (error) return;

                    isVector = true;
                    $('.img').attr('src', path.join(app.getPath('temp'), 'potrace.svg'));

                    //console.log(clipboard.availableFormats());
                    //clipboard.writeHtml(fs.readFileSync(path.join(app.getPath('temp'), 'potrace.svg')), 'text/svg');
                });
            });
        });

    });
});
<commit_msg>convert editor window to es6<commit_after>const remote = require('electron').remote;
const app = remote.app;
const dialog = remote.dialog;
const clipboard = remote.clipboard;

const execFile = require('child_process').execFile;
const fs = require('fs');
const os = require('os');
const path = require('path');

const Jimp = require('jimp');

$(() => {
    const imageURL = decodeURIComponent(window.location.href.split('?lastURL=')[1]);
    const platform = os.platform();
    let isVector = false;

    $('.img').attr('src', imageURL);

    $('.save').on('click', () => {
        if (isVector) {
            const savePath = dialog.showSaveDialog({
                filters: [{
                    name: 'Images', extensions: ['svg']
                }]
            });

            if (savePath) {
                fs.writeFileSync(savePath, fs.readFileSync(path.join(app.getPath('temp'), 'potrace.svg')));
            }
        } else {
            // save canvas as png
        }
    });

    $('.vector').on('click', () => {
        Jimp.read(imageURL, (error, image) => {
            if (error) return;

            const imgPath = path.join(app.getPath('temp'), 'potrace.bmp');

            let binPath;
            if (platform == 'darwin') {
                binPath = path.join(app.getAppPath(), 'bin', 'osx', 'potrace');
            } else if (platform == 'win32') {
                binPath = path.join(app.getAppPath(), 'bin', 'win', 'potrace.exe');
            } else {
                return;
            }

            image.write(imgPath, () => {
                execFile(binPath, ['-s', '-n', imgPath], (error, stdout) => {
                    if (error) return;

                    isVector = true;
                    $('.img').attr('src', path.join(app.getPath('temp'), 'potrace.svg'));

                    // console.log(clipboard.availableFormats());
                    // clipboard.writeHtml(fs.readFileSync(path.join(app.getPath('temp'), 'potrace.svg')), 'text/svg');
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  Appear,
  BlockQuote,
  Cite,
  CodePane,
  Deck,
  Fill,
  Heading,
  Image,
  Layout,
  Link,
  ListItem,
  List,
  Markdown,
  Quote,
  Slide,
  Spectacle,
  Text
} from "spectacle";

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "../themes/polis/index.js";

// Import custom component
import Interactive from "../assets/interactive";

// Require CSS
require("normalize.css");
require("../themes/polis/index.css");

const images = {
  tain: require("../assets/tain.png"),
  sunflowerRev: require("../assets/sunflowerRev.png"),
  pnyx: require("../assets/pnyx.jpg"),
  oldcrowd: require("../assets/oldcrowd.png"),
  matrix: require("../assets/matrix.png"),
  fergusonexplosion: require("../assets/fergusonexplosion.gif"),
  everyByEvery: require("../assets/everyByEvery.jpg"),
  emirates: require("../assets/emirates.png"),
  confFlameWar: require("../assets/confFlameWar.png"),
  assembly: require("../assets/assembly.png"),
  parisCafe: require("../assets/pariscafe.png"),
  consultation: require("../assets/consultation.jpg"),
  shoutyourabortion: require("../assets/shoutyourabortion.gif"),
  fergusonTweeters: require("../assets/fergusonTweeters.jpg"),
  shoutyourabortion2: require("../assets/shoutyourabortion2.jpg"),
  commentbot: require("../assets/commentbot.jpg"),
  bookquote: require("../assets/bookquote.jpg"),
  vtaiwan: require("../assets/vtaiwan.png"),
  jsdc_endorsement: require("../assets/jsdc_endorsement.png"),
  jsdc_invite: require("../assets/jsdc_invite.png"),
  jsdc_majority: require("../assets/jsdc_majority.png"),
  write: require("../assets/write.jpg"),
  vote: require("../assets/vote.jpg"),
  buzzfeedGuardian: require("../assets/buzzfeedGuardian.gif"),
  parliament: require("../assets/sunflowerParliament.jpg"),
  athensNumbered: require("../assets/athensNumbered.jpg"),
  athensFromAbove: require("../assets/athensFromAbove.jpg"),
  survey: require("../assets/survey.jpg"),
  leaveComment: require("../assets/leaveComment.png"),
  alien: require("../assets/alien.jpg"),
  cheeseheads: require("../assets/cheeseheads.jpg"),
  jaclyn: require("../assets/jaclyn.png"),
  recommender: require("../assets/recommender.png"),
  commentMatrix: require("../assets/commentMatrix.png"),

  // fergusonTweeters: require("../assets/fergusonTweeters.jpg"),
};

preloader(images);

const theme = createTheme({
  primary: "rgb(47, 49, 54)"
});

export default class Presentation extends React.Component {
  render() {
    return (
      <Spectacle theme={theme}>
        <Deck transition={["fade", "slide"]} progress="number" transitionDuration={500}>
{
  /*************
    Welcome slide
  **************/
}
<Slide notes={`I'm colin, thank you to clkao, audrey and the gov zero team for having me`} bgColor="primary">
  <Heading size={1} fit caps lineHeight={2}>
    pol.is in Taiwan
  </Heading>
  <Heading lineHeight={1.3} size={5}>
    Bridging the gap between
    public discourse & public policy
  </Heading>
  <Text lineHeight={2} bold textColor="tertiary">Taipei, g0v 2016</Text>
</Slide>

{
  /*************
    What does a crowd think?
  **************/
}
<Slide
  notes={`
    this is the question our company has been trying to address with the product pol.is
    which many of you are familiar with ---

    every org ---

    simple and fast see the answer more often ---

    our company infrastructure for democratic behavior, part of gov zero's function as well ---

    have everyone shout out what they like ---

    `}>
  <Heading size={3} lineHeight={1.3}>
    What does a crowd think?
  </Heading>
</Slide>

<Slide
  bgImage={images.emirates.replace("/", "")}
  notes={`
    begin with crowd --

    visualize because ---

    midfield ---

    surveys +-, comments +-, interviews +-

  `}>
</Slide>
<Slide
  notes={`
    let's go back to the classical city state, the polis, a more human scale and see what they did ---

    The crowd was endlessly passing through the Agora freely discussing issues

  `}
  bgImage={images.athensFromAbove.replace("/", "")} />
<Slide notes={`todo`}>
  <Image
    style={{
      position: "relative",
      left: -300
    }}
    width="180%" src={images.assembly.replace("/", "")}/>
</Slide>
<Slide
  notes={`

    we're locked into representative government, which means that the only way in which we're still a democracy has to do with public opinion and sentiment gathering. when and how we do this and how it affects the process.

    inconvenient boring and slow ---

    serial ---

    `}
    bgDarken={.5}
    bgImage={images.consultation.replace("/", "")}>
    <Heading size={1} lineHeight={1.3}>
      Inefficient
    </Heading>
</Slide>
<Slide
  notes={`
    sometimes the stadium shows up ---

    find out exactly what they think. ---

    infrequent, not always constructive, not sustainable ---

    usually means something has broken down. ---

    the government would love to not do research like this.
    `}
    bgImage={images.parliament.replace("/", "")}/>

  {
    /*************
      Social media
    **************/
  }
  <Slide
    notes={`
      social media *is* where we're talking ---

      both q & q ---

      authentic ---

      why is it problematic ?
      `}
    >
    <Heading size={3} lineHeight={1.3}>
      Social media sentiment
    </Heading>
  </Slide>

{
  /*************
    Emma's work
  **************/
}
<Slide
  notes={`
    So let's say you do have a data scientist ---

    The following images produced by Stanford researcher and Rhodes Scholar Emma Pierson. ---

    These are liberal and conservative twitter users talking about Ferguson ---

    They are ignoring each other ---

    ferguson very controversial about race in america --

    the unit of interaction is affinity (person or idea) ---

    what emerges from these rules is a graph. ---

    The filter bubble is quantifiable.
  `}
  bgImage={images.fergusonTweeters.replace("/", "")} />
<Slide

  notes={`
    does this pattern repeat? ---

    2.5 days of Twitter activity ---

    different 'communities' or, literally, parts of the Twitter graph
    talk amongst themselves about the same topics. ---

    they are clusters that emerge from affinity, following your own. You are
    broadcasting ideas from people you agree with to people who agree with you. ---

    discovery was the goal
  `}>
  <Image width={"70%"} src={images.shoutyourabortion.replace("/", "")}/>
</Slide>
<Slide
notes={`
  Publishers are reaching both communities with articles, special role.
  polis is moving forward with publishers who are trying to move beyond
  vitriol on the comment threads below their articles and better serve
  this unique purpose of providing common ground, mediation and moderation
  `}
  bgImage={images.buzzfeedGuardian.replace("/", "")} />
<Slide
  notes={`
    twitter not 'one place' ---

    graphs, neighborhoods w/ diff assumptions, values and patterns. ---

    not one conversation occurring where ideas bump up against
    each other, the conversation retreats into thousands of self
    selected networks of likeminded people. ---

    a reply to a community a reply to a person, which is very heavy, hard to come off not as an attack.

    tribe isn't a bad thing. ---

    People feel safe with people they relate to ---

    intra group, not inter group. ---

    social media overall not a great place for inter-group argumentation ---

  `}
  bgImage={images.shoutyourabortion2.replace("/", "")}>
</Slide>

{
  /*************
    Case Study
  **************/
}
<Slide
  notes={`
    lots of people, strongly divergent views, in real-time
    what it grew into here in Taiwan, the implications for other places.
    overview of pol.is for those of you who are not familiar
  `}
  >
  <Heading size={3} lineHeight={1.3}>
    I want to tell you about a time that arguing on the internet went well.
  </Heading>
</Slide>
<Slide notes={`200 comment thread, fast and furious, here are the last comments`}>
  <Image style={{borderRadius: 5}} width="60%" src={images.confFlameWar.replace("/", "")}/>
</Slide>
<Slide notes={`what did this mean? well everyone came into the conversation and if they had something to say, they could write it, just like on facebook or any other platform`}>
  <Image style={{borderRadius: 5}} width="100%" src={images.write.replace("/", "")}/>
</Slide>
<Slide notes={`
  and we have a different set of responses, agree and disagree, you cannot reply
  `}>
  <Image style={{borderRadius: 5}} width="100%" src={images.vote.replace("/", "")}/>
</Slide>
<Slide notes={`

    it gets you a matrix. and all those ones
    and zeros may not seem more useful than everyone talking at once in a confused way... but the fact is that you
    have run a kind of compression algorithm on the crowd's perspectives, an encoding you have transferred the
    state of the crowd's opinions into a mathematical structure that statistical
    operations can be run on.

    parallellize! everyone writes and votes at the same time, analysis
    done automatically. ---

    `}>
  <Image style={{borderRadius: 5}} width="70%" src={images.commentMatrix.replace("/", "")}/>
</Slide>
<Slide
  notes={`

  `}>
  <Image style={{borderRadius: 5}} width="70%" src={images.recommender.replace("/", "")}/>

</Slide>
<Slide notes={`todo`}>
  <Heading lineHeight={1.3}> Real-time Machine Learning </Heading>
</Slide>
<Slide notes={`
  polis identifies groups based on similar voting patterns, per conversation
  `}>
  <Heading lineHeight={1.3}> {`Clustering (formation of groups)`} </Heading>
</Slide>
<Slide notes={`Allowing Qihoo employees to share tech isn't an endorsement`}>
  <Image style={{borderRadius: 5}} width="80%" src={images.jsdc_endorsement.replace("/", "")}/>
</Slide>
<Slide notes={``}>
  <Image style={{borderRadius: 5}} width="80%" src={images.jsdc_invite.replace("/", "")}/>
</Slide>
<Slide notes={`
    A magical thing happened -
    broad consensus on a community building statement of mutual respect and trust
    it colors the other statements. it's now respectful disagreement
  `}>
  <Image style={{borderRadius: 5}} width="80%" src={images.jsdc_majority.replace("/", "")}/>
</Slide>

<Slide notes={`
  how do you turn a mob into a deliberative body? ---

  polis is just a medium, it takes people who want a better world to use it
  that, meaning all of you, is what inspires us.

  as a methodology for creating change I believe we can think about digital infrastructure much the same way
  as in the physical world, where installing an airport in a remote region
  might encourage new growth and economic activity. Make it easy, people will do it. --

  turning raw crowd energy into meaningful feedback --> vTaiwan.
  Making this scale and character crowd energy and feedback a daily, weekly, monthly occurrance.
  Make it sustainable
`} bgImage={images.sunflowerRev.replace("/", "")}/>

{
  /*************
    vTaiwan as a model
  **************/
}

<Slide
  bgImage={images.vtaiwan.replace("/", "")}
  notes={`
    into legislative impact
    vTaiwan is a model for the world
    Quote / discuss with Audrey

    what is so extraordinary is that sunflower has been treasured and maintained and collaborated on
  `}>
    <Heading size={3} lineHeight={1.3}>

    </Heading>
</Slide>

<Slide
  bgImage={images.jaclyn.replace("/", "")}
  notes={`

  `}>
    <Heading size={3} lineHeight={1.3}>

    </Heading>
</Slide>

<Slide
  notes={`
    efficient educated judgement is the holy grail - broke a deadlock that lasted 6 years in 3months
    `}>
  <Text lineHeight={1.7} textAlign="left" textSize={36} textFont="Source Serif Pro">
    {`
      Democratic governance rests on the capacity of and opportunity for
      citizens to engage in enlightened debate. Although deciding public
      policy through argument has little to recommend it in terms of
      efficiency, the purpose of public deliberation, as Aristotle recognized
      in his Rhetoric, is not efficient government but educated judgement.
    `}
  </Text>
  <Link
    textColor="white"
    textSize={24}
    href="https://books.google.com/books?id=7UuCvESagZsC&lpg=PA82&ots=dNr1WC9gmm">
    {"Gerald Hauser, On Habermas & the Public Sphere"}
  </Link>
</Slide>

<Slide notes={`
    leading the world in the implementation of digital
    democracy practices, you're doing it in the shadow of a regime that is moving
    full speed in the other direction. ---

    deepest respect for your efforts in this regard and am humbled to able to contribute. ---

    polis has been used in other places by other groups, adoption in Taiwan
    has been taken to its conclusion of influencing a legislative decision. ---

    it is so powerful and exciting to see people have agenda setting power in vTaiwan because that's where the real power is, we started polis to break the media stranglehold on agenda setting power of the parties, we wanted agenda setting, which is the real power, to be bottom up. ---

    We can't fulfil our mission of building a
    tool to affect policy without a people and a government willing to engage in
    listening, and for that we thank you too. It motivates and inspires us.

    run a polis convo with the crowd here?

  `}
    bgImage={images.tain.replace("/", "")}>
  </Slide>

        </Deck>
      </Spectacle>
    );
  }
}
<commit_msg>weaving in survey comment pro con vs polis<commit_after>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  Appear,
  BlockQuote,
  Cite,
  CodePane,
  Deck,
  Fill,
  Heading,
  Image,
  Layout,
  Link,
  ListItem,
  List,
  Markdown,
  Quote,
  Slide,
  Spectacle,
  Text
} from "spectacle";

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
import createTheme from "../themes/polis/index.js";

// Import custom component
import Interactive from "../assets/interactive";

// Require CSS
require("normalize.css");
require("../themes/polis/index.css");

const images = {
  tain: require("../assets/tain.png"),
  sunflowerRev: require("../assets/sunflowerRev.png"),
  pnyx: require("../assets/pnyx.jpg"),
  oldcrowd: require("../assets/oldcrowd.png"),
  matrix: require("../assets/matrix.png"),
  fergusonexplosion: require("../assets/fergusonexplosion.gif"),
  everyByEvery: require("../assets/everyByEvery.jpg"),
  emirates: require("../assets/emirates.png"),
  confFlameWar: require("../assets/confFlameWar.png"),
  assembly: require("../assets/assembly.png"),
  parisCafe: require("../assets/pariscafe.png"),
  consultation: require("../assets/consultation.jpg"),
  shoutyourabortion: require("../assets/shoutyourabortion.gif"),
  fergusonTweeters: require("../assets/fergusonTweeters.jpg"),
  shoutyourabortion2: require("../assets/shoutyourabortion2.jpg"),
  commentbot: require("../assets/commentbot.jpg"),
  bookquote: require("../assets/bookquote.jpg"),
  vtaiwan: require("../assets/vtaiwan.png"),
  jsdc_endorsement: require("../assets/jsdc_endorsement.png"),
  jsdc_invite: require("../assets/jsdc_invite.png"),
  jsdc_majority: require("../assets/jsdc_majority.png"),
  write: require("../assets/write.jpg"),
  vote: require("../assets/vote.jpg"),
  buzzfeedGuardian: require("../assets/buzzfeedGuardian.gif"),
  parliament: require("../assets/sunflowerParliament.jpg"),
  athensNumbered: require("../assets/athensNumbered.jpg"),
  athensFromAbove: require("../assets/athensFromAbove.jpg"),
  survey: require("../assets/survey.jpg"),
  leaveComment: require("../assets/leaveComment.png"),
  alien: require("../assets/alien.jpg"),
  cheeseheads: require("../assets/cheeseheads.jpg"),
  jaclyn: require("../assets/jaclyn.png"),
  recommender: require("../assets/recommender.png"),
  commentMatrix: require("../assets/commentMatrix.png"),

  // fergusonTweeters: require("../assets/fergusonTweeters.jpg"),
};

preloader(images);

const theme = createTheme({
  primary: "rgb(47, 49, 54)"
});

export default class Presentation extends React.Component {
  render() {
    return (
      <Spectacle theme={theme}>
        <Deck transition={["fade", "slide"]} progress="number" transitionDuration={500}>
{
  /*************
    Welcome slide
  **************/
}
<Slide notes={`I'm colin, thank you to clkao, audrey and the gov zero team for having me`} bgColor="primary">
  <Heading size={1} fit caps lineHeight={2}>
    pol.is in Taiwan
  </Heading>
  <Heading lineHeight={1.3} size={5}>
    Bridging the gap between
    public discourse & public policy
  </Heading>
  <Text lineHeight={2} bold textColor="tertiary">Taipei, g0v 2016</Text>
</Slide>

{
  /*************
    What does a crowd think?
  **************/
}
<Slide
  notes={`
    this is the question our company has been trying to address with the product pol.is
    which many of you are familiar with ---

    every org ---

    simple and fast see the answer more often ---

    our company infrastructure for democratic behavior, part of gov zero's function as well ---

    have everyone shout out what they like ---

    `}>
  <Heading size={3} lineHeight={1.3}>
    What does a crowd think?
  </Heading>
</Slide>

<Slide
  bgImage={images.emirates.replace("/", "")}
  notes={`
    begin with crowd --

    visualize because ---

    midfield ---

    surveys +-, comments +-, interviews +-

  `}>
</Slide>
<Slide
  notes={`
    let's go back to the classical city state, the polis, a more human scale and see what they did ---

    The crowd was endlessly passing through the Agora freely discussing issues

  `}
  bgImage={images.athensFromAbove.replace("/", "")} />
<Slide notes={`todo`}>
  <Image
    style={{
      position: "relative",
      left: -300
    }}
    width="180%" src={images.assembly.replace("/", "")}/>
</Slide>
<Slide
  notes={`

    we're locked into representative government, which means that the only way in which we're still a democracy has to do with public opinion and sentiment gathering. when and how we do this and how it affects the process.

    inconvenient boring and slow ---

    serial ---

    `}
    bgDarken={.5}
    bgImage={images.consultation.replace("/", "")}>
    <Heading size={1} lineHeight={1.3}>
      Inefficient
    </Heading>
</Slide>
<Slide
  notes={`
    sometimes the stadium shows up ---

    find out exactly what they think. ---

    infrequent, not always constructive, not sustainable ---

    usually means something has broken down. ---

    the government would love to not do research like this.
    `}
    bgImage={images.parliament.replace("/", "")}/>

  {
    /*************
      Social media
    **************/
  }
  <Slide
    notes={`
      social media *is* where we're talking ---

      both q & q ---

      authentic ---

      why is it problematic ?
      `}
    >
    <Heading size={3} lineHeight={1.3}>
      Social media sentiment
    </Heading>
  </Slide>

{
  /*************
    Emma's work
  **************/
}
<Slide
  notes={`
    So let's say you do have a data scientist ---

    The following images produced by Stanford researcher and Rhodes Scholar Emma Pierson. ---

    These are liberal and conservative twitter users talking about Ferguson ---

    They are ignoring each other ---

    ferguson very controversial about race in america --

    the unit of interaction is affinity (person or idea) ---

    what emerges from these rules is a graph. ---

    The filter bubble is quantifiable.
  `}
  bgImage={images.fergusonTweeters.replace("/", "")} />
<Slide

  notes={`
    does this pattern repeat? ---

    2.5 days of Twitter activity ---

    different 'communities' or, literally, parts of the Twitter graph
    talk amongst themselves about the same topics. ---

    they are clusters that emerge from affinity, following your own. You are
    broadcasting ideas from people you agree with to people who agree with you. ---

    discovery was the goal
  `}>
  <Image width={"70%"} src={images.shoutyourabortion.replace("/", "")}/>
</Slide>
<Slide
notes={`
  Publishers are reaching both communities with articles, special role.
  polis is moving forward with publishers who are trying to move beyond
  vitriol on the comment threads below their articles and better serve
  this unique purpose of providing common ground, mediation and moderation
  `}
  bgImage={images.buzzfeedGuardian.replace("/", "")} />
<Slide
  notes={`
    twitter not 'one place' ---

    graphs, neighborhoods w/ diff assumptions, values and patterns. ---

    not one conversation occurring where ideas bump up against
    each other, the conversation retreats into thousands of self
    selected networks of likeminded people. ---

    a reply to a community a reply to a person, which is very heavy, hard to come off not as an attack.

    tribe isn't a bad thing. ---

    People feel safe with people they relate to ---

    intra group, not inter group. ---

    social media overall not a great place for inter-group argumentation ---

  `}
  bgImage={images.shoutyourabortion2.replace("/", "")}>
</Slide>

{
  /*************
    Case Study
  **************/
}
<Slide
  notes={`
    lots of people, strongly divergent views, in real-time
    what it grew into here in Taiwan, the implications for other places.
    overview of pol.is for those of you who are not familiar
  `}
  >
  <Heading size={3} lineHeight={1.3}>
    I want to tell you about a time that arguing on the internet went well.
  </Heading>
</Slide>
<Slide notes={`200 comment thread, fast and furious, here are the last comments`}>
  <Image style={{borderRadius: 5}} width="60%" src={images.confFlameWar.replace("/", "")}/>
</Slide>
<Slide notes={`what did this mean? well everyone came into the conversation and if they had something to say, they could write it, just like on facebook or any other platform`}>
  <Image style={{borderRadius: 5}} width="100%" src={images.write.replace("/", "")}/>
</Slide>
<Slide notes={`
  and we have a different set of responses, agree and disagree, you cannot reply
  `}>
  <Image style={{borderRadius: 5}} width="100%" src={images.vote.replace("/", "")}/>
</Slide>
<Slide notes={`

    matrix ---
    scalable ---
    may not seem more useful ---
    kind of compression algorithm on the crowd's perspectives, an encoding you have transferred the
    state of the crowd's opinions into a mathematical structure that statistical
    operations can be run on.

    parallellization ---

    `}>
  <Image style={{borderRadius: 5}} width="70%" src={images.commentMatrix.replace("/", "")}/>
</Slide>
<Slide
  notes={`

  `}>
  <Image style={{borderRadius: 5}} width="70%" src={images.recommender.replace("/", "")}/>

</Slide>
<Slide notes={`todo`}>
  <Heading lineHeight={1.3}> Real-time Machine Learning </Heading>
</Slide>
<Slide notes={`
  polis identifies groups based on similar voting patterns, per conversation
  `}>
  <Heading lineHeight={1.3}> {`Clustering (formation of groups)`} </Heading>
</Slide>
<Slide notes={`Allowing Qihoo employees to share tech isn't an endorsement`}>
  <Image style={{borderRadius: 5}} width="80%" src={images.jsdc_endorsement.replace("/", "")}/>
</Slide>
<Slide notes={``}>
  <Image style={{borderRadius: 5}} width="80%" src={images.jsdc_invite.replace("/", "")}/>
</Slide>
<Slide notes={`
    magical, consensus shows mutual respect ---

    like the good of surveys, this is structured, useful data. but like commenting it's emergent, bottom up, organic, authentic.
    has the best features of both, and overcomes the disadvantages of both.
  `}>
  <Image style={{borderRadius: 5}} width="80%" src={images.jsdc_majority.replace("/", "")}/>
</Slide>

<Slide notes={`
  how do you turn a mob into a deliberative body? ---

  polis is just a medium, it takes people who want a better world to use it
  that, meaning all of you, is what inspires us.

  as a methodology for creating change I believe we can think about digital infrastructure much the same way
  as in the physical world, where installing an airport in a remote region
  might encourage new growth and economic activity. Make it easy, people will do it. --

  turning raw crowd energy into meaningful feedback --> vTaiwan.
  Making this scale and character crowd energy and feedback a daily, weekly, monthly occurrance.
  Make it sustainable
`} bgImage={images.sunflowerRev.replace("/", "")}/>

{
  /*************
    vTaiwan as a model
  **************/
}

<Slide
  bgImage={images.vtaiwan.replace("/", "")}
  notes={`
    into legislative impact
    vTaiwan is a model for the world
    Quote / discuss with Audrey

    what is so extraordinary is that sunflower has been treasured and maintained and collaborated on
  `}>
    <Heading size={3} lineHeight={1.3}>

    </Heading>
</Slide>

<Slide
  bgImage={images.jaclyn.replace("/", "")}
  notes={`

  `}>
    <Heading size={3} lineHeight={1.3}>

    </Heading>
</Slide>

<Slide
  notes={`
    efficient educated judgement is the holy grail - broke a deadlock that lasted 6 years in 3months
    `}>
  <Text lineHeight={1.7} textAlign="left" textSize={36} textFont="Source Serif Pro">
    {`
      Democratic governance rests on the capacity of and opportunity for
      citizens to engage in enlightened debate. Although deciding public
      policy through argument has little to recommend it in terms of
      efficiency, the purpose of public deliberation, as Aristotle recognized
      in his Rhetoric, is not efficient government but educated judgement.
    `}
  </Text>
  <Link
    textColor="white"
    textSize={24}
    href="https://books.google.com/books?id=7UuCvESagZsC&lpg=PA82&ots=dNr1WC9gmm">
    {"Gerald Hauser, On Habermas & the Public Sphere"}
  </Link>
</Slide>

<Slide notes={`
    leading the world in the implementation of digital
    democracy practices, you're doing it in the shadow of a regime that is moving
    full speed in the other direction. ---

    deepest respect for your efforts in this regard and am humbled to able to contribute. ---

    polis has been used in other places by other groups, adoption in Taiwan
    has been taken to its conclusion of influencing a legislative decision. ---

    it is so powerful and exciting to see people have agenda setting power in vTaiwan because that's where the real power is, we started polis to break the media stranglehold on agenda setting power of the parties, we wanted agenda setting, which is the real power, to be bottom up. ---

    We can't fulfil our mission of building a
    tool to affect policy without a people and a government willing to engage in
    listening, and for that we thank you too. It motivates and inspires us.

    run a polis convo with the crowd here?

  `}
    bgImage={images.tain.replace("/", "")}>
  </Slide>

        </Deck>
      </Spectacle>
    );
  }
}
<|endoftext|>


<commit_before>var FullScreenFallback = function() {
	FullScreenFallback._super.constructor.apply(this, arguments);
	this._DEFAULT_OPTIONS = $.extend({}, this._DEFAULT_OPTIONS, {
		'styles': {
			'position': 'absolute',
			'zIndex': '2147483647',
			'left': 0,
			'top': 0,
			'bottom': 0,
			'right': 0
		}
	});
	this.__delegateKeydownHandler();
};

extend(FullScreenFallback, FullScreenAbstract, {
	__isFullScreen: false,
	__delegateKeydownHandler: function() {
		var $doc = $(document);
		$doc.delegate('*', 'keydown.fullscreen', $.proxy(this.__keydownHandler, this));
		var data = JQ_LT_17 ? $doc.data('events') : $._data(document).events;
		var events = data['keydown'];
		if (!JQ_LT_17) {
			events.splice(0, 0, events.splice(events.delegateCount - 1, 1)[0]);
		} else {
			data.live.unshift(data.live.pop());
		}
	},
	__keydownHandler: function(e) {
		if (this.isFullScreen() && e.which === 27) {
			this.exit();
			return false;
		}
		return true;
	},
	_revertStyles: function() {
		FullScreenFallback._super._revertStyles.apply(this, arguments);
		// force redraw (fixes bug in IE7 with content dissapearing)
		this._fullScreenElement.offsetHeight;
	},
	open: function(elem) {
		FullScreenFallback._super.open.apply(this, arguments);
		this.__isFullScreen = true;
		this._fullScreenChange();
	},
	exit: function() {
		if (!this.__isFullScreen) {
			return;
		}
		this.__isFullScreen = false;
		this._fullScreenChange();
	},
	isFullScreen: function() {
		return this.__isFullScreen;
	},
	element: function() {
		return this.__isFullScreen ? this._fullScreenElement : null;
	}
});<commit_msg>switch back to position: fixed otherwise the fallback won't work on pages larger than the viewport of the device<commit_after>var FullScreenFallback = function() {
	FullScreenFallback._super.constructor.apply(this, arguments);
	this._DEFAULT_OPTIONS = $.extend({}, this._DEFAULT_OPTIONS, {
		'styles': {
			'position': 'fixed',
			'zIndex': '2147483647',
			'left': 0,
			'top': 0,
			'bottom': 0,
			'right': 0
		}
	});
	this.__delegateKeydownHandler();
};

extend(FullScreenFallback, FullScreenAbstract, {
	__isFullScreen: false,
	__delegateKeydownHandler: function() {
		var $doc = $(document);
		$doc.delegate('*', 'keydown.fullscreen', $.proxy(this.__keydownHandler, this));
		var data = JQ_LT_17 ? $doc.data('events') : $._data(document).events;
		var events = data['keydown'];
		if (!JQ_LT_17) {
			events.splice(0, 0, events.splice(events.delegateCount - 1, 1)[0]);
		} else {
			data.live.unshift(data.live.pop());
		}
	},
	__keydownHandler: function(e) {
		if (this.isFullScreen() && e.which === 27) {
			this.exit();
			return false;
		}
		return true;
	},
	_revertStyles: function() {
		FullScreenFallback._super._revertStyles.apply(this, arguments);
		// force redraw (fixes bug in IE7 with content dissapearing)
		this._fullScreenElement.offsetHeight;
	},
	open: function(elem) {
		FullScreenFallback._super.open.apply(this, arguments);
		this.__isFullScreen = true;
		this._fullScreenChange();
	},
	exit: function() {
		if (!this.__isFullScreen) {
			return;
		}
		this.__isFullScreen = false;
		this._fullScreenChange();
	},
	isFullScreen: function() {
		return this.__isFullScreen;
	},
	element: function() {
		return this.__isFullScreen ? this._fullScreenElement : null;
	}
});<|endoftext|>