<commit_before>/*
 @author Zakai Hamilton
 @component CacheManager
 */

screens.cache.manager = function StorageCache(me, { core, storage }) {
    me.metadataPath = () => {
        if (screens.platform === "server") {
            return "server/metadata";
        }
        else {
            return "local/metadata";
        }
    };
    me.update = async (path, unique = null) => {
        let cache = null;
        const cachePath = me.path(path);
        if (screens.platform === "server") {
            if (unique && unique === me.unique(path)) {
                return null;
            }
            cache = await me.load(path);
        }
        else {
            cache = await core.message.send_server(me.id + ".get", path);
        }
        const body = cache ? JSON.stringify(cache, null, 4) : "";
        const metadataPath = me.metadataPath();
        await storage.fs.createPath(metadataPath);
        if (path) {
            await storage.fs.createPath(metadataPath + "/" + path);
        }
        await storage.fs.writeFile(cachePath, body, "utf8");
        return cache;
    };
    me.path = path => {
        path = path || "";
        var [, component] = me.id.split(".");
        const metadataPath = me.metadataPath();
        return [metadataPath, path, component + ".json"].filter(Boolean).join("/");
    };
    me.unique = async path => {
        let unique;
        try {
            const metadata = await storage.fs.stat(me.path(path));
            if (metadata) {
                unique = metadata.size;
            }
        }
        catch (err) {
            unique = 0;
        }
        return unique;
    };
    me.get = async (path, update, unique) => {
        const cachePath = me.path(path);
        if (update) {
            return await me.update(path, unique);
        }
        let buffer = null;
        try {
            buffer = await storage.fs.readFile(cachePath, "utf8");
        }
        catch (err) {
            return await me.update(path, unique);
        }
        let cache = null;
        if (buffer && buffer.length && typeof buffer === "string") {
            try {
                cache = JSON.parse(buffer);
            }
            catch (err) {
                // eslint-disable-next-line no-console
                console.error(me.id + ": file '" + path + "' does not have a valid JSON, error: " + err + " buffer: " + buffer);
            }
        }
        me.push(path, async () => {
            const unique = await me.unique(path);
            return { unique, update, path };
        });
        return cache;
    };
    me.bulk = async (requests) => {
        for (const request of requests) {
            const { path, update, unique } = request;
            request.result = await me.get(path, update, unique);
        }
        return requests;
    };
    me.push = (path, callback) => {
        const metadataPath = me.metadataPath();
        if (!me.queue) {
            me.queue = [];
        }
        const exists = me.queue.find(item => item.path === path);
        if (exists) {
            return;
        }
        me.queue.push({
            path,
            callback
        });
        if (!me.timer) {
            me.timer = setTimeout(async () => {
                clearTimeout(me.timer);
                me.timer = null;
                let requests = [];
                for (; ;) {
                    const item = me.queue.pop();
                    if (!item) {
                        break;
                    }
                    const request = await item.callback();
                    requests.push(request);
                }
                requests = await core.message.send_server(me.id + ".bulk", requests);
                for (const request of requests) {
                    if (!request.result) {
                        continue;
                    }
                    await storage.fs.createPath(metadataPath);
                    if (request.path) {
                        await storage.fs.createPath(metadataPath + "/" + request.path);
                    }
                    const cachePath = me.path(request.path);
                    const body = JSON.stringify(request.result, null, 4);
                    await storage.fs.writeFile(cachePath, body, "utf8");
                }
            }, 1000);
        }
    };
};
<commit_msg>buffer length in console error<commit_after>/*
 @author Zakai Hamilton
 @component CacheManager
 */

screens.cache.manager = function StorageCache(me, { core, storage }) {
    me.metadataPath = () => {
        if (screens.platform === "server") {
            return "server/metadata";
        }
        else {
            return "local/metadata";
        }
    };
    me.update = async (path, unique = null) => {
        let cache = null;
        const cachePath = me.path(path);
        if (screens.platform === "server") {
            if (unique && unique === me.unique(path)) {
                return null;
            }
            cache = await me.load(path);
        }
        else {
            cache = await core.message.send_server(me.id + ".get", path);
        }
        const body = cache ? JSON.stringify(cache, null, 4) : "";
        const metadataPath = me.metadataPath();
        await storage.fs.createPath(metadataPath);
        if (path) {
            await storage.fs.createPath(metadataPath + "/" + path);
        }
        await storage.fs.writeFile(cachePath, body, "utf8");
        return cache;
    };
    me.path = path => {
        path = path || "";
        var [, component] = me.id.split(".");
        const metadataPath = me.metadataPath();
        return [metadataPath, path, component + ".json"].filter(Boolean).join("/");
    };
    me.unique = async path => {
        let unique;
        try {
            const metadata = await storage.fs.stat(me.path(path));
            if (metadata) {
                unique = metadata.size;
            }
        }
        catch (err) {
            unique = 0;
        }
        return unique;
    };
    me.get = async (path, update, unique) => {
        const cachePath = me.path(path);
        if (update) {
            return await me.update(path, unique);
        }
        let buffer = null;
        try {
            buffer = await storage.fs.readFile(cachePath, "utf8");
        }
        catch (err) {
            return await me.update(path, unique);
        }
        let cache = null;
        if (buffer && buffer.length && typeof buffer === "string") {
            try {
                cache = JSON.parse(buffer);
            }
            catch (err) {
                // eslint-disable-next-line no-console
                console.error(me.id + ": file '" + path + "' does not have a valid JSON, error: " + err + " length: " + buffer.length + " buffer: " + buffer);
            }
        }
        me.push(path, async () => {
            const unique = await me.unique(path);
            return { unique, update, path };
        });
        return cache;
    };
    me.bulk = async (requests) => {
        for (const request of requests) {
            const { path, update, unique } = request;
            request.result = await me.get(path, update, unique);
        }
        return requests;
    };
    me.push = (path, callback) => {
        const metadataPath = me.metadataPath();
        if (!me.queue) {
            me.queue = [];
        }
        const exists = me.queue.find(item => item.path === path);
        if (exists) {
            return;
        }
        me.queue.push({
            path,
            callback
        });
        if (!me.timer) {
            me.timer = setTimeout(async () => {
                clearTimeout(me.timer);
                me.timer = null;
                let requests = [];
                for (; ;) {
                    const item = me.queue.pop();
                    if (!item) {
                        break;
                    }
                    const request = await item.callback();
                    requests.push(request);
                }
                requests = await core.message.send_server(me.id + ".bulk", requests);
                for (const request of requests) {
                    if (!request.result) {
                        continue;
                    }
                    await storage.fs.createPath(metadataPath);
                    if (request.path) {
                        await storage.fs.createPath(metadataPath + "/" + request.path);
                    }
                    const cachePath = me.path(request.path);
                    const body = JSON.stringify(request.result, null, 4);
                    await storage.fs.writeFile(cachePath, body, "utf8");
                }
            }, 1000);
        }
    };
};
<|endoftext|>


<commit_before>##register is_present : -> bool
##args()
{
    var present = MindWave.displayIcon();
    if (present) MindWave.setSignalValue(250);
    return present;
}

##register get_attention_level : -> int
##args()
{
    return MindWave.getAttentionLevel();
}

##register get_meditation_level : -> int
##args()
{
    return MindWave.getMeditationLevel();
}

##register get_blink_strength : -> int
##args()
{
    var bs = MindWave.getBlinkStrength();
    if (bs > 0) MindWave.setBlinkStrength(-1);
    return bs;
}
<commit_msg>removed the presence clearance<commit_after>##register is_present : -> bool
##args()
{
    var present = MindWave.displayIcon();
    //if (present) MindWave.setSignalValue(250);
    return present;
}

##register get_attention_level : -> int
##args()
{
    return MindWave.getAttentionLevel();
}

##register get_meditation_level : -> int
##args()
{
    return MindWave.getMeditationLevel();
}

##register get_blink_strength : -> int
##args()
{
    var bs = MindWave.getBlinkStrength();
    if (bs > 0) MindWave.setBlinkStrength(-1);
    return bs;
}
<|endoftext|>


<commit_before>const path = require('path')
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')

module.exports = {
  mode: 'development',
  devtool: 'source-map',
  entry: './src/index.tsx',
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'public'),
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
    plugins: [
      new TsconfigPathsPlugin({
        configFile: './tsconfig.json',
      }),
    ],
  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        commons: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        options: {
          transpileOnly: true,
        },
        exclude: /node_modules/,
      },
    ],
  },
}
<commit_msg>fix build<commit_after>const path = require('path')
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')

module.exports = {
  mode: 'development',
  devtool: 'source-map',
  entry: './src/index.tsx',
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'public'),
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
    plugins: [
      new TsconfigPathsPlugin({
        configFile: './tsconfig.json',
      }),
    ],
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        options: {
          transpileOnly: true,
        },
        exclude: /node_modules/,
      },
    ],
  },
}
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const chokidar = require('chokidar');

const logger = require('./log');

let copyFile = require('./copyFile'); // eslint-disable-line prefer-const

function onWatchTripped(p, assetBase, basePath, dir, copyOptions) {
  const subPath = p.replace(assetBase, '');
  const destination = path.resolve(basePath, dir.public + '/' + subPath);
  copyFile(p, destination, copyOptions);
}

const watchAssets = (
  patternlab,
  basePath,
  dir,
  key,
  copyOptions,
  watchOnce
) => {
  const assetBase = path.resolve(basePath, dir.source);
  logger.debug(`Pattern Lab is watching ${assetBase} for changes`);

  if (patternlab.watchers[key]) {
    patternlab.watchers[key].close();
  }
  const assetWatcher = chokidar.watch(assetBase, {
    ignored: /(^|[\/\\])\../,
    ignoreInitial: false,
    awaitWriteFinish: {
      stabilityThreshold: 200,
      pollInterval: 100,
    },
    persistent: !watchOnce,
  });

  //watch for changes and copy
  assetWatcher
    .on('add', p => {
      onWatchTripped(p, assetBase, basePath, dir, copyOptions);
    })
    .on('change', p => {
      onWatchTripped(p, assetBase, basePath, dir, copyOptions);
    });

  patternlab.watchers[key] = assetWatcher;
};

module.exports = watchAssets;
<commit_msg>feat(uikits): support watched-asset copying<commit_after>'use strict';

const path = require('path');
const _ = require('lodash');
const chokidar = require('chokidar');

const logger = require('./log');

let copyFile = require('./copyFile'); // eslint-disable-line prefer-const

function onWatchTripped(patternlab, p, assetBase, basePath, dir, copyOptions) {
  const subPath = p.replace(assetBase, '');
  _.each(patternlab.uikits, uikit => {
    const destination = path.resolve(
      basePath,
      uikit.outputDir,
      dir.public + '/' + subPath
    );
    copyFile(p, destination, copyOptions);
  });
}

const watchAssets = (
  patternlab,
  basePath,
  dir,
  key,
  copyOptions,
  watchOnce
) => {
  const assetBase = path.resolve(basePath, dir.source);
  logger.debug(`Pattern Lab is watching ${assetBase} for changes`);

  if (patternlab.watchers[key]) {
    patternlab.watchers[key].close();
  }
  const assetWatcher = chokidar.watch(assetBase, {
    ignored: /(^|[\/\\])\../,
    ignoreInitial: false,
    awaitWriteFinish: {
      stabilityThreshold: 200,
      pollInterval: 100,
    },
    persistent: !watchOnce,
  });

  //watch for changes and copy
  assetWatcher
    .on('add', p => {
      onWatchTripped(patternlab, p, assetBase, basePath, dir, copyOptions);
    })
    .on('change', p => {
      onWatchTripped(patternlab, p, assetBase, basePath, dir, copyOptions);
    });

  patternlab.watchers[key] = assetWatcher;
};

module.exports = watchAssets;
<|endoftext|>


<commit_before><commit_msg>Use push carousel<commit_after><|endoftext|>


<commit_before>var path = require('path');
var webpack = require('webpack');
var AssetsPlugin = require('assets-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var autoprefixer = require('autoprefixer');

module.exports = {

  entry: {
    app: [
      path.join(__dirname, 'src/shared/theme/styles/app.scss'),
      path.join(__dirname, 'src/client/client.prod.js')
    ],
    vendor: [
      "es6-promise",
      "isomorphic-fetch",
      "react",
      "react-dom",
      "react-helmet",
      "react-redux",
      "react-router",
      "react-router-redux",
      "react-router-scroll",
      "redux",
      "reselect"
    ]
  },

  output: {
    path: path.join(__dirname, "static", "build"),
    publicPath: "/build/",
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].chunk.js'
  },

  module: {
    loaders: [
      {
        test: /\.js?$/,
        exclude: /node_modules|\.git/,
        loader: 'babel-loader',
        query: {
          babelrc: false,
          presets: [
            ["es2015", { "modules": false, loose: true }],
            "react",
            "stage-0"
          ],
          plugins: [
            "lodash",
            "transform-react-constant-elements",
            "transform-react-remove-prop-types",
            "transform-react-pure-class-to-function"
          ]
        }
      }, {
        test: /\.css$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: 'css-loader'
        })
      }, {
        test: /\.scss$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: 'css?modules&importLoaders=2&localIdentName=[name]__[local]___[hash:base64:5]&minimize!postcss!sass'
        })
      }, {
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        loader: 'file-loader',
      }, {
        test: /\.(jpg|png|gif)$/,
        loaders: [
          'file-loader',
          'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}'
        ],
      }, {
        test: /\.json$/,
        loader: 'json-loader'
      }
    ]
  },

  resolve: {
    extensions: ['', '.json', '.js', '.jsx'],
    modules: [
      path.join(__dirname, 'src'),
      path.join(__dirname, 'node_modules')
    ]
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production'),
        'BROWSER': JSON.stringify(true)
      }
    }),
    new webpack.optimize.OccurrenceOrderPlugin(true),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false
      }
    }),
    new AssetsPlugin({
      filename: 'assets.json',
      path: path.join(__dirname, 'static'),
      prettyPrint: true
    }),
    new ExtractTextPlugin({
      filename: '[name].[contenthash].css',
      allChunks: true
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: Infinity
    })
  ],

  postcss: [
    autoprefixer({ browsers: ['last 2 versions', 'IE > 10'] })
  ],

  sassLoader: {
    includePaths: [path.join(__dirname, "src/shared/theme/styles")]
  }
};<commit_msg>extract more vendors<commit_after>var path = require('path');
var webpack = require('webpack');
var AssetsPlugin = require('assets-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var autoprefixer = require('autoprefixer');

module.exports = {

  entry: {
    app: [
      path.join(__dirname, 'src/shared/theme/styles/app.scss'),
      path.join(__dirname, 'src/client/client.prod.js')
    ],
    vendor: [
      "es6-promise",
      "isomorphic-fetch",
      "firebase",
      "normalizr",
      "react",
      "react-dom",
      "react-helmet",
      "react-redux",
      "react-router",
      "react-router-redux",
      "react-router-scroll",
      "redux",
      "redux-thunk",
      "reselect"
    ]
  },

  output: {
    path: path.join(__dirname, "static", "build"),
    publicPath: "/build/",
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].chunk.js'
  },

  module: {
    loaders: [
      {
        test: /\.js?$/,
        exclude: /node_modules|\.git/,
        loader: 'babel-loader',
        query: {
          babelrc: false,
          presets: [
            ["es2015", { "modules": false, loose: true }],
            "react",
            "stage-0"
          ],
          plugins: [
            "lodash",
            "transform-react-constant-elements",
            "transform-react-remove-prop-types",
            "transform-react-pure-class-to-function"
          ]
        }
      }, {
        test: /\.css$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: 'css-loader'
        })
      }, {
        test: /\.scss$/,
        exclude: /node_modules/,
        loader: ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: 'css?modules&importLoaders=2&localIdentName=[name]__[local]___[hash:base64:5]&minimize!postcss!sass'
        })
      }, {
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        loader: 'file-loader',
      }, {
        test: /\.(jpg|png|gif)$/,
        loaders: [
          'file-loader',
          'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}'
        ],
      }, {
        test: /\.json$/,
        loader: 'json-loader'
      }
    ]
  },

  resolve: {
    extensions: ['', '.json', '.js', '.jsx'],
    modules: [
      path.join(__dirname, 'src'),
      path.join(__dirname, 'node_modules')
    ]
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production'),
        'BROWSER': JSON.stringify(true)
      }
    }),
    new webpack.optimize.OccurrenceOrderPlugin(true),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false
      }
    }),
    new AssetsPlugin({
      filename: 'assets.json',
      path: path.join(__dirname, 'static'),
      prettyPrint: true
    }),
    new ExtractTextPlugin({
      filename: '[name].[contenthash].css',
      allChunks: true
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      minChunks: Infinity
    })
  ],

  postcss: [
    autoprefixer({ browsers: ['last 2 versions', 'IE > 10'] })
  ],

  sassLoader: {
    includePaths: [path.join(__dirname, "src/shared/theme/styles")]
  }
};<|endoftext|>


<commit_before>"use strict";

var constants = require('./common/Constants'),
    util = require('./common/Utilities');

$(document).ready(function ()
{
    var here = window.location.pathname;
    if (here.charAt(here.length-1) != '/')
    {
        here = here + '/';
    }

    $('a.button').button();

    $('#csv-upload-dialog').dialog({
        autoOpen: false,
        width: 400,
        height: 400,
        modal: true,
        buttons: {
            'Cancel': function ()
            {
                $(this).dialog('close');
            },
            'Upload': function ()
            {
                $(this).find('form').submit();
            }
        }
    });

    $('#csv-upload-button').button().click(function ()
    {
        $('#csv-upload-dialog').dialog('open');
    });

    $('#new-student-dialog').dialog({
        autoOpen: false,
        width: 350,
        height: 400,
        modal: true,
        buttons: {
            'Cancel': function ()
            {
                $(this).dialog('close');
            },
            'Add student': function ()
            {
                submitNewStudent();
            }
        },
        close: function ()
        {
            $(this).find('input').val('');
        },
        open: function ()
        {
            $(this).find('input[name="rosterID"]').focus();
        }
    });

    $('#new-student-dialog').keyup(function (e)
    {
        if (e.keyCode == 13)
        {
            submitNewStudent();
            return false;
        }
    });

    $('#new-student-button').button().click(function ()
    {
        $('#new-student-dialog').dialog('open');
    });

    // Table data

    function connectGridToDataView(grid, dataView)
    {
        grid.onSort.subscribe(function (e, args)
        {
            var sortAsc = args.sortAsc,
                sortCol = args.sortCol,
                field = sortCol.field;

            var sortFun = function (item1, item2)
            {
                var a = item1[field],
                    b = item2[field];
                return util.compare(a, b);
            };
            dataView.sort(sortFun, sortAsc);
        });
        dataView.onRowCountChanged.subscribe(function (e, args)
        {
            grid.updateRowCount();
            grid.render();
        });
        dataView.onRowsChanged.subscribe(function (e, args)
        {
            grid.invalidateRows(args.rows);
            grid.render();
        });
    }

    function formatTimestamp(row, cell, value, columnDef, dataContext)
    {
        return util.dateFormat(value * 1000, 'm/d HH:MM');
    }
    function formatDuration(row, cell, value, columnDef, dataContext)
    {
        return Math.round(value / 1000) + ' s'
    }
    function formatMedal(row, cell, value, columnDef, dataContext)
    {
        var medal = constants.medal.codeToString(value);
        return '
' + medal + '
';
    }
    function formatEndState(row, cell, value, columnDef, dataContext)
    {
        var endState = constants.endState.codeToString(value);
        return '
' + endState + '
';
    }

    var selectedStudentLoginIDs = [];
    var studentDataView = new Slick.Data.DataView();
    var studentGrid = new Slick.Grid($('#student-table'), studentDataView,
        [
            {id:'instructorLoginID', field:'instructorLoginID', name:'Instructor', sortable:true},
            {id:'rosterID', field:'rosterID', name:'Roster ID', sortable:true},
            {id:'firstName', field:'firstName', name:'First Name', sortable:true},
            {id:'lastName', field:'lastName', name:'Last Name', sortable:true},
            {id:'loginID', field:'loginID', name:'Login ID', sortable:true},
            {id:'password', field:'password', name:'Password'},
            {id:'condition', field:'condition', name:'Condition', sortable:true},
            {id:'gameCount', field:'gameCount', name:'Games', sortable:true}
        ],
        {
            forceFitColumns: true
        });
    studentGrid.setSelectionModel(new Slick.RowSelectionModel());
    studentGrid.onSelectedRowsChanged.subscribe(function ()
    {
        selectedStudentLoginIDs = [];
        var rows = studentGrid.getSelectedRows();
        for (var i = 0; i < rows.length; i++)
        {
            selectedStudentLoginIDs.push(studentDataView.getItem(rows[i]).loginID);
        }
        gamesDataView.refresh();
    });
    connectGridToDataView(studentGrid, studentDataView);

    var gamesDataView = new Slick.Data.DataView();
    var gamesGrid = new Slick.Grid($('#games-table'), gamesDataView,
        [
            {id:'loginID', field:'loginID', name:'Login ID', sortable:true},
            {id:'condition', field:'condition', name:'Condition', sortable:true},
            {id:'stageID', field:'stageID', name:'Level', sortable:true},
            {id:'questionSetID', field:'questionSetID', name:'Set', sortable:true},
            {id:'score', field:'score', name:'Score', sortable:true, width: 65},
            {id:'medal', field:'medal', name:'Medal', sortable:true, formatter:formatMedal, width:55},
            {id:'elapsedMS', field:'elapsedMS', name:'Duration', sortable:true, formatter:formatDuration, width: 60},
            {id:'endTime', field:'endTime', name:'Date', sortable:true, formatter:formatTimestamp},
            {id:'endState', field:'endState', name:'End', sortable:true, formatter:formatEndState}
        ],
        {
            forceFitColumns: true,
            multiSelect: false
        });
    gamesDataView.setFilter(function (item)
    {
        return (selectedStudentLoginIDs.length == 0 ||
                ~selectedStudentLoginIDs.indexOf(item.loginID));
    });
    gamesGrid.setSelectionModel(new Slick.RowSelectionModel());
    gamesGrid.onSelectedRowsChanged.subscribe(function ()
    {
        var item = gamesDataView.getItem(gamesGrid.getSelectedRows()[0]);
        if (item)
        {
            $.get(here + '../output/' + item.dataFile)
            .success(function (data, status, jqXHR)
            {
                $('#game-output').val(jqXHR.responseText);
            })
            .error(makeXHRErrorHandler('Error fetching game output: '));
        }
        else
        {
            $('#game-output').val('');
        }
    });
    connectGridToDataView(gamesGrid, gamesDataView);

    // Fetch the table data.
    fetchStudents();
    fetchResults();

    function makeXHRErrorHandler(message)
    {
        return function (jqXHR)
        {
            alert(message + jqXHR.responseText);
        };
    }

    function fetchStudents(instructorID)
    {
        //$.getJSON(here + instructorID + '/student')
        $.getJSON(here + 'student')
        .success(function (data)
        {
            studentDataView.beginUpdate();
            studentDataView.setItems(data.students);
            studentDataView.endUpdate();
        })
        .error(makeXHRErrorHandler('Error fetching students: '));
    }

    function fetchResults()
    {
        $.getJSON(here + 'student/result')
        .success(function (data)
        {
            gamesDataView.beginUpdate();
            gamesDataView.setItems(data.results);
            gamesDataView.endUpdate();
        })
        .error(makeXHRErrorHandler('Error fetching game results: '));
    }

    function submitNewStudent()
    {
        $.post(here + 'student', $('#new-student-dialog form').serialize())
            .success(function (data)
            {
                studentDataView.addItem(data.student);
                $('#new-student-dialog').dialog('close');
            })
            .error(function (jqXHR, statusText, errorThrown)
            {
                alert('Error saving student: ' + jqXHR.responseText);
            })
            .complete(function ()
            {
                //unlock();
            });
    }
});
<commit_msg>Sort game results by date by default. plus some code cleanup.<commit_after>"use strict";

var constants = require('./common/Constants'),
    util = require('./common/Utilities');

$(document).ready(function ()
{
    var here = window.location.pathname;
    if (here.charAt(here.length-1) != '/')
    {
        here = here + '/';
    }

    $('a.button').button();

    $('#csv-upload-dialog').dialog({
        autoOpen: false,
        width: 400,
        height: 400,
        modal: true,
        buttons: {
            'Cancel': function ()
            {
                $(this).dialog('close');
            },
            'Upload': function ()
            {
                $(this).find('form').submit();
            }
        }
    });

    $('#csv-upload-button').button().click(function ()
    {
        $('#csv-upload-dialog').dialog('open');
    });

    $('#new-student-dialog').dialog({
        autoOpen: false,
        width: 350,
        height: 400,
        modal: true,
        buttons: {
            'Cancel': function ()
            {
                $(this).dialog('close');
            },
            'Add student': function ()
            {
                submitNewStudent();
            }
        },
        close: function ()
        {
            $(this).find('input').val('');
        },
        open: function ()
        {
            $(this).find('input[name="rosterID"]').focus();
        }
    });

    $('#new-student-dialog').keyup(function (e)
    {
        if (e.keyCode == 13)
        {
            submitNewStudent();
            return false;
        }
    });

    $('#new-student-button').button().click(function ()
    {
        $('#new-student-dialog').dialog('open');
    });

    // Table data

    function connectGridToDataView(grid, dataView)
    {
        grid.onSort.subscribe(function (e, args)
        {
            var sortAsc = args.sortAsc,
                sortCol = args.sortCol,
                field = sortCol.field;

            var sortFun = function (item1, item2)
            {
                var a = item1[field],
                    b = item2[field];
                return util.compare(a, b);
            };
            dataView.sort(sortFun, sortAsc);
        });
        dataView.onRowCountChanged.subscribe(function (e, args)
        {
            grid.updateRowCount();
            grid.render();
        });
        dataView.onRowsChanged.subscribe(function (e, args)
        {
            grid.invalidateRows(args.rows);
            grid.render();
        });
    }

    function formatTimestamp(row, cell, value, columnDef, dataContext)
    {
        return util.dateFormat(value * 1000, 'm/d HH:MM');
    }
    function formatDuration(row, cell, value, columnDef, dataContext)
    {
        return Math.round(value / 1000) + ' s'
    }
    function formatMedal(row, cell, value, columnDef, dataContext)
    {
        var medal = constants.medal.codeToString(value);
        return '
' + medal + '
';
    }
    function formatEndState(row, cell, value, columnDef, dataContext)
    {
        var endState = constants.endState.codeToString(value);
        return '
' + endState + '
';
    }

    var selectedStudentLoginIDs = [];
    var studentDataView = new Slick.Data.DataView();
    var studentGrid = new Slick.Grid($('#student-table'), studentDataView,
        [
            {id:'instructorLoginID', field:'instructorLoginID', name:'Instructor', sortable:true},
            {id:'rosterID', field:'rosterID', name:'Roster ID', sortable:true},
            {id:'firstName', field:'firstName', name:'First Name', sortable:true},
            {id:'lastName', field:'lastName', name:'Last Name', sortable:true},
            {id:'loginID', field:'loginID', name:'Login ID', sortable:true},
            {id:'password', field:'password', name:'Password'},
            {id:'condition', field:'condition', name:'Condition', sortable:true},
            {id:'gameCount', field:'gameCount', name:'Games', sortable:true}
        ],
        {
            forceFitColumns: true
        });
    studentGrid.setSelectionModel(new Slick.RowSelectionModel());
    studentGrid.onSelectedRowsChanged.subscribe(function ()
    {
        selectedStudentLoginIDs = [];
        var rows = studentGrid.getSelectedRows();
        for (var i = 0; i < rows.length; i++)
        {
            selectedStudentLoginIDs.push(studentDataView.getItem(rows[i]).loginID);
        }
        gamesDataView.refresh();
    });
    connectGridToDataView(studentGrid, studentDataView);

    var gamesDataView = new Slick.Data.DataView();
    var gamesGrid = new Slick.Grid($('#games-table'), gamesDataView,
        [
            {id:'loginID', field:'loginID', name:'Login ID', sortable:true},
            {id:'condition', field:'condition', name:'Condition', sortable:true},
            {id:'stageID', field:'stageID', name:'Level', sortable:true},
            {id:'questionSetID', field:'questionSetID', name:'Set', sortable:true},
            {id:'score', field:'score', name:'Score', sortable:true, width: 65},
            {id:'medal', field:'medal', name:'Medal', sortable:true, formatter:formatMedal, width:55},
            {id:'elapsedMS', field:'elapsedMS', name:'Duration', sortable:true, formatter:formatDuration, width: 60},
            {id:'endTime', field:'endTime', name:'Date', sortable:true, formatter:formatTimestamp},
            {id:'endState', field:'endState', name:'End', sortable:true, formatter:formatEndState}
        ],
        {
            forceFitColumns: true,
            multiSelect: false
        });
    gamesDataView.setFilter(function (item)
    {
        return (selectedStudentLoginIDs.length == 0 ||
                ~selectedStudentLoginIDs.indexOf(item.loginID));
    });
    gamesGrid.setSortColumn('endTime', false);
    gamesGrid.setSelectionModel(new Slick.RowSelectionModel());
    gamesGrid.onSelectedRowsChanged.subscribe(function ()
    {
        var item = gamesDataView.getItem(gamesGrid.getSelectedRows()[0]);
        if (item)
        {
            $.get(here + '../output/' + item.dataFile)
            .success(function (data, status, jqXHR)
            {
                $('#game-output').val(jqXHR.responseText);
            })
            .error(makeXHRErrorHandler('Error fetching game output: '));
        }
        else
        {
            $('#game-output').val('');
        }
    });
    connectGridToDataView(gamesGrid, gamesDataView);

    // Fetch the table data.
    fetchStudents();
    fetchResults();

    function makeXHRErrorHandler(message)
    {
        return function (jqXHR)
        {
            alert(message + jqXHR.responseText);
        };
    }

    function fetchStudents(instructorID)
    {
        $.getJSON(here + 'student')
        .success(function (data)
        {
            studentDataView.beginUpdate();
            studentDataView.setItems(data.students);
            studentDataView.endUpdate();
        })
        .error(makeXHRErrorHandler('Error fetching students: '));
    }

    function fetchResults()
    {
        $.getJSON(here + 'student/result')
        .success(function (data)
        {
            gamesDataView.beginUpdate();
            gamesDataView.setItems(data.results);
            gamesDataView.reSort();
            gamesDataView.endUpdate();
        })
        .error(makeXHRErrorHandler('Error fetching game results: '));
    }

    function submitNewStudent()
    {
        $.post(here + 'student', $('#new-student-dialog form').serialize())
        .success(function (data)
        {
            studentDataView.addItem(data.student);
            $('#new-student-dialog').dialog('close');
        })
        .error(function (jqXHR, statusText, errorThrown)
        {
            alert('Error saving student: ' + jqXHR.responseText);
        })
        .complete(function ()
        {
            //unlock();
        });
    }
});
<|endoftext|>


<commit_before>// ==UserScript==
// @id             iitc-plugin-portal-names@zaso
// @name           IITC plugin: Portal Names
// @category       Layer
// @version        0.1.1.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Show portal names on the map
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

// use own namespace for plugin
window.plugin.portalNames = function() {};

window.plugin.portalNames.MAX_PORTALS = 400;
window.plugin.portalNames.NAME_WIDTH = 80;
window.plugin.portalNames.NAME_HEIGHT = 23;

window.plugin.portalNames.labelLayers = {};
window.plugin.portalNames.labelLayerGroup = null;

window.plugin.portalNames.setupCSS = function() {
  $("<style>").prop("type", "text/css").html(''
  +'.plugin-portal-names{'
    +'color:#FFFFBB;'
    +'font-size:11px;line-height:12px;'
    +'text-align:center;padding: 2px;'  // padding needed so shadow doesn't clip
    +'overflow:hidden;'
// could try this if one-line names are used
//    +'white-space: nowrap;text-overflow:ellipsis;'
    +'text-shadow:1px 1px #000,1px -1px #000,-1px 1px #000,-1px -1px #000, 0 0 5px #000;'
    +'pointer-events:none;'
  +'}'
  ).appendTo("head");
}

window.plugin.portalNames.portalAdded = function(data) {
  data.portal.on('add', function() {
    window.plugin.portalNames.addLabel(this.options.guid, this.getLatLng());
  });
  data.portal.on('remove', function() {
    window.plugin.portalNames.removeLabel(this.options.guid);
  });
}

window.plugin.portalNames.removeLabel = function(guid) {
  var previousLayer = window.plugin.portalNames.labelLayers[guid];
  if(previousLayer) {
    window.plugin.portalNames.labelLayerGroup.removeLayer(previousLayer);
    delete plugin.portalNames.labelLayers[guid];
  }
}

window.plugin.portalNames.addLabel = function(guid, latLng) {
  var previousLayer = window.plugin.portalNames.labelLayers[guid];
  if (!previousLayer) {

    var d = window.portals[guid].options.details;
    var portalName = d.portalV2.descriptiveText.TITLE;

    var label = L.marker(latLng, {
      icon: L.divIcon({
        className: 'plugin-portal-names',
        iconAnchor: [window.plugin.portalNames.NAME_WIDTH/2,0],
        iconSize: [window.plugin.portalNames.NAME_WIDTH,window.plugin.portalNames.NAME_HEIGHT],
        html: portalName
      }),
      guid: guid,
    });
    window.plugin.portalNames.labelLayers[guid] = label;
    label.addTo(window.plugin.portalNames.labelLayerGroup);
  }
}

window.plugin.portalNames.updatePortalLabels = function() {

  var portalPoints = {};

  for (var guid in window.portals) {
    var p = window.portals[guid];
    if (p._map) {  // only consider portals added to the map
      var point = map.project(p.getLatLng());
      portalPoints[guid] = point;
    }
  }

  if (Object.keys(portalPoints).length > window.plugin.portalNames.MAX_PORTALS) {
    // too manuy VISIBLE portals to handle quickly - clear all
    window.plugin.portalNames.labelLayerGroup.clearLayers();
    window.plugin.portalNames.labelLayers = {};
    return;
  }

  var coveredPortals = {};

  for (var guid in portalPoints) {
    var point = portalPoints[guid];
    // the bounds used for testing are twice as wide as the portal name marker. this is so that there's no left/right
    // overlap between two different portals text
    var largeBounds = L.bounds (
              point.subtract([window.plugin.portalNames.NAME_WIDTH,0]),
              point.add([window.plugin.portalNames.NAME_WIDTH,window.plugin.portalNames.NAME_HEIGHT])
    );

    for (var otherGuid in portalPoints) {
      if (guid != otherGuid) {
        var otherPoint = portalPoints[otherGuid];

        if (largeBounds.contains(otherPoint)) {
          // another portal is within the rectangle for this one's name - so no name for this one
          coveredPortals[guid] = true;
          break;
        }
      }
    }
  }

  for (var guid in coveredPortals) {
    delete portalPoints[guid];
  }

  // remove any not wanted
  for (var guid in window.plugin.portalNames.labelLayers) {
    if (!(guid in portalPoints)) {
      window.plugin.portalNames.removeLabel(guid);
    }
  }

  // and add those we do
  for (var guid in portalPoints) {
    window.plugin.portalNames.addLabel(guid, portals[guid].getLatLng());
  }
}

var setup = function() {
  window.plugin.portalNames.setupCSS();

  window.plugin.portalNames.labelLayerGroup = new L.LayerGroup();
  window.addLayerGroup('Portal Names', window.plugin.portalNames.labelLayerGroup, true);

  window.addHook('requestFinished', window.plugin.portalNames.updatePortalLabels);
  window.addHook('mapDataRefreshEnd', window.plugin.portalNames.updatePortalLabels);
  window.map.on('overlayadd overlayremove', window.plugin.portalNames.updatePortalLabels);
}

// PLUGIN END //////////////////////////////////////////////////////////

@@PLUGINEND@@
<commit_msg>make portal-names work however many portals are on screen, by using buckets to group portals for more efficient overlap testing<commit_after>// ==UserScript==
// @id             iitc-plugin-portal-names@zaso
// @name           IITC plugin: Portal Names
// @category       Layer
// @version        0.1.2.@@DATETIMEVERSION@@
// @namespace      https://github.com/jonatkins/ingress-intel-total-conversion
// @updateURL      @@UPDATEURL@@
// @downloadURL    @@DOWNLOADURL@@
// @description    [@@BUILDNAME@@-@@BUILDDATE@@] Show portal names on the map
// @include        https://www.ingress.com/intel*
// @include        http://www.ingress.com/intel*
// @match          https://www.ingress.com/intel*
// @match          http://www.ingress.com/intel*
// @grant          none
// ==/UserScript==

@@PLUGINSTART@@

// PLUGIN START ////////////////////////////////////////////////////////

// use own namespace for plugin
window.plugin.portalNames = function() {};

window.plugin.portalNames.NAME_WIDTH = 80;
window.plugin.portalNames.NAME_HEIGHT = 23;

window.plugin.portalNames.labelLayers = {};
window.plugin.portalNames.labelLayerGroup = null;

window.plugin.portalNames.setupCSS = function() {
  $("<style>").prop("type", "text/css").html(''
  +'.plugin-portal-names{'
    +'color:#FFFFBB;'
    +'font-size:11px;line-height:12px;'
    +'text-align:center;padding: 2px;'  // padding needed so shadow doesn't clip
    +'overflow:hidden;'
// could try this if one-line names are used
//    +'white-space: nowrap;text-overflow:ellipsis;'
    +'text-shadow:1px 1px #000,1px -1px #000,-1px 1px #000,-1px -1px #000, 0 0 5px #000;'
    +'pointer-events:none;'
  +'}'
  ).appendTo("head");
}

window.plugin.portalNames.portalAdded = function(data) {
  data.portal.on('add', function() {
    window.plugin.portalNames.addLabel(this.options.guid, this.getLatLng());
  });
  data.portal.on('remove', function() {
    window.plugin.portalNames.removeLabel(this.options.guid);
  });
}

window.plugin.portalNames.removeLabel = function(guid) {
  var previousLayer = window.plugin.portalNames.labelLayers[guid];
  if(previousLayer) {
    window.plugin.portalNames.labelLayerGroup.removeLayer(previousLayer);
    delete plugin.portalNames.labelLayers[guid];
  }
}

window.plugin.portalNames.addLabel = function(guid, latLng) {
  var previousLayer = window.plugin.portalNames.labelLayers[guid];
  if (!previousLayer) {

    var d = window.portals[guid].options.details;
    var portalName = d.portalV2.descriptiveText.TITLE;

    var label = L.marker(latLng, {
      icon: L.divIcon({
        className: 'plugin-portal-names',
        iconAnchor: [window.plugin.portalNames.NAME_WIDTH/2,0],
        iconSize: [window.plugin.portalNames.NAME_WIDTH,window.plugin.portalNames.NAME_HEIGHT],
        html: portalName
      }),
      guid: guid,
    });
    window.plugin.portalNames.labelLayers[guid] = label;
    label.addTo(window.plugin.portalNames.labelLayerGroup);
  }
}

window.plugin.portalNames.updatePortalLabels = function() {

  var portalPoints = {};

  for (var guid in window.portals) {
    var p = window.portals[guid];
    if (p._map) {  // only consider portals added to the map
      var point = map.project(p.getLatLng());
      portalPoints[guid] = point;
    }
  }

  // for efficient testing of intersection, group portals into buckets based on the label size
  var buckets = {};
  for (var guid in portalPoints) {
    var point = portalPoints[guid];

    var bucketId = L.point([Math.floor(point.x/(window.plugin.portalNames.NAME_WIDTH*2)),Math.floor(point.y/window.plugin.portalNames.NAME_HEIGHT)]);
    // the guid is added to four buckets. this way, when testing for overlap we don't need to test
    // all 8 buckets surrounding the one around the particular portal, only the bucket it is in itself
    var bucketIds = [bucketId, bucketId.add([1,0]), bucketId.add([0,1]), bucketId.add([1,1])];
    for (var i in bucketIds) {
      var b = bucketIds[i].toString();
      if (!buckets[b]) buckets[b] = {};
      buckets[b][guid] = true;
    }
  }

  var coveredPortals = {};

  for (var bucket in buckets) {
    var bucketGuids = buckets[bucket];
    for (var guid in bucketGuids) {
      var point = portalPoints[guid];
      // the bounds used for testing are twice as wide as the portal name marker. this is so that there's no left/right
      // overlap between two different portals text
      var largeBounds = L.bounds (
                point.subtract([window.plugin.portalNames.NAME_WIDTH,0]),
                point.add([window.plugin.portalNames.NAME_WIDTH,window.plugin.portalNames.NAME_HEIGHT])
      );

      for (var otherGuid in bucketGuids) {
        if (guid != otherGuid) {
          var otherPoint = portalPoints[otherGuid];

          if (largeBounds.contains(otherPoint)) {
            // another portal is within the rectangle for this one's name - so no name for this one
            coveredPortals[guid] = true;
            break;
          }
        }
      }
    }
  }

  for (var guid in coveredPortals) {
    delete portalPoints[guid];
  }

  // remove any not wanted
  for (var guid in window.plugin.portalNames.labelLayers) {
    if (!(guid in portalPoints)) {
      window.plugin.portalNames.removeLabel(guid);
    }
  }

  // and add those we do
  for (var guid in portalPoints) {
    window.plugin.portalNames.addLabel(guid, portals[guid].getLatLng());
  }
}

var setup = function() {
  window.plugin.portalNames.setupCSS();

  window.plugin.portalNames.labelLayerGroup = new L.LayerGroup();
  window.addLayerGroup('Portal Names', window.plugin.portalNames.labelLayerGroup, true);

  window.addHook('requestFinished', window.plugin.portalNames.updatePortalLabels);
  window.addHook('mapDataRefreshEnd', window.plugin.portalNames.updatePortalLabels);
  window.map.on('overlayadd overlayremove', window.plugin.portalNames.updatePortalLabels);
}

// PLUGIN END //////////////////////////////////////////////////////////

@@PLUGINEND@@
<|endoftext|>


<commit_before>#!/usr/bin/env node

var
    fs = require("fs"),
    program = require("commander"),
    pkgJSON = require("./package.json"),
    stdin = process.stdin,
    stdinData = "",
    prettify = false,
    verbose = false;

program
    .version(pkgJSON.version)
    .usage("[options] [file ...]")
    .description("A simple CLI tool to shrink/minify or prettify JSON data.")
    .option("-p, --pretty", "prettify JSON data", "true")
    .option(
        "-o, --outputFile <file>",
        "write output to <file> instead of stdout"
    )
    .option(
        "-v, --verbose",
        "makes stdout more verbose/talkative. Mostly useful for debugging.",
        "true"
    )
    .parse(process.argv);

// extra checks to avoid version & verbose conflict bug
if(!program.verbose && program.version && typeof program.version!="function"){
    console.log(program.version);
    process.exit(1);
}

if(program.pretty){ prettify = true; }
if(program.verbose){ verbose = true; }

message("Check for file paths...");

if(stdin.isTTY){
    if(program.args){

        message("Found file paths: " + program.args);

        program.args.forEach(function(arg){

            message("Reading file: " + arg);

            fs.readFile( arg, function (err, data) {

                if(err){
                    console.error("Can't read file: " + arg);
                    process.exit(1);
                }

                prettyMiniIt(data.toString());

            });

        });

    }
}
else{

    message("Found standard input...");

    stdin.on(
        "data",
        function(chunk){
            stdinData += chunk;
        }
    );

    stdin.on(
        "end",
        function(){
            prettyMiniIt(stdinData);
        }
    );

}

function prettyMiniIt(data){
    var jsonData, output;

    try{
        jsonData = JSON.parse(data);
    }
    catch(e){
        console.error("Can't parse JSON data");
        console.error(e);
        process.exit(1);
    }

    output = prettify
        ? JSON.stringify(jsonData, null, 4)
        : JSON.stringify(jsonData);

    if(program.outputFile){
        message("Writing output file...");

        fs.writeFile(program.outputFile, output, function(err2){
            if(err2){
                console.error(err2);
                process.exit(1);
            }
            else{
                console.log("File saved as " + program.outputFile);
            }
        });
    }
    else{
        console.log(output);
    }
}

function message(msg){
    if(verbose){
        console.log(msg);
    }
}
<commit_msg>add support for url data source and multiple output files using indexed suffix<commit_after>#!/usr/bin/env node

var
    fs = require("fs"),
    program = require("commander"),
    request = require("request"),
    pkgJSON = require("./package.json"),
    stdin = process.stdin,
    stdinData = "",
    prettify = false,
    verbose = false;

program
    .version(pkgJSON.version)
    .usage("[options] [file | url ...]")
    .description("A simple CLI tool to shrink/minify or prettify JSON data.")
    .option("-p, --pretty", "prettify JSON data", "true")
    .option(
        "-o, --outputFile <file>",
        "write output to <file> instead of stdout"
    )
    .option(
        "-v, --verbose",
        "makes stdout more verbose/talkative. Mostly useful for debugging.",
        "true"
    )
    .parse(process.argv);

// extra checks to avoid version & verbose conflict bug
if(!program.verbose && program.version && typeof program.version!="function"){
    console.log(program.version);
    process.exit(1);
}

if(program.pretty){ prettify = true; }
if(program.verbose){ verbose = true; }

message("Check for data source(s)...");

if(stdin.isTTY){
    if(program.args.length>0){

        message("Found data source(s): " + program.args);

        program.args.forEach(function(arg, indx){
            var readCallback;

            if(isValidURL(arg)){
                message("Requesting file: " + arg);

                request(
                    arg,
                    function(error, response, body){
                        if(!error && response.statusCode == 200){
                            prettyMiniIt(body);
                        }
                        else{
                            console.error("Can't retrieve file from: " + arg);
                            process.exit(1);
                        }
                    }
                );
            }
            else{
                message("Reading file ("+indx+"): " + arg);

                readCallback = function (err, data) {
                    if(err){
                        console.error("Can't read file: " + arg);
                    }
                    else if(indx>0){
                        prettyMiniIt(data.toString(), indx);
                    }
                    else{
                        prettyMiniIt(data.toString());
                    }
                }

                fs.readFile(arg, readCallback);
            }
        });
    }
    else{
        console.error("Missing source data.");
    }
}
else{

    message("Found standard input...");

    stdin.on(
        "data",
        function(chunk){
            stdinData += chunk;
        }
    );

    stdin.on(
        "end",
        function(){
            prettyMiniIt(stdinData);
        }
    );

}

function prettyMiniIt(data, suffix){
    var jsonData, output, outputFile;

    try{
        jsonData = JSON.parse(data);
    }
    catch(e){
        console.error("Can't parse JSON data");
        console.error(e);
        return;
    }

    output = prettify
        ? JSON.stringify(jsonData, null, 4)
        : JSON.stringify(jsonData);

    if(program.outputFile){
        message("Writing output file...");
        outputFile = program.outputFile;

        if(suffix){
            outputFile = outputFile.split(".");

            outputFile.splice(
                outputFile.length-1,
                0,
                suffix
            );

            outputFile = outputFile.join(".");
        }

        fs.writeFile(outputFile, output, function(err2){
            if(err2){
                console.error(err2);
                process.exit(1);
            }
            else{
                console.log("File saved as " + outputFile);
            }
        });
    }
    else{
        console.log(output);
    }
}

function message(msg){
    if(verbose){
        console.log(msg);
    }
}

function isValidURL(str){
	if(typeof str!=="string") return false;

	return (/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/).test(str);
}
<|endoftext|>


<commit_before>const axios = require('axios');
const searchCivicAddressId = function (searchString, context) {
  const pool = context.pool;
  const myQuery = `SELECT civicaddress_id, pinnum, address from coagis.bc_address where cast(civicaddress_id as TEXT) LIKE '${searchString}%'  limit 5`;
  return pool.query(myQuery)
    .then((result) => {
      if (result.rows.length === 0) return { type: 'civicAddressId', results: [] };

      const finalResult = {
        type: 'civicAddressId',
        results: result.rows.map((address) => {
          return {
            score: 33,
            type: 'civicAddressId',
            id: address.civicaddress_id,
            civic_address_id: address.civicaddress_id,
            address: address.address,
            pinnum: address.pinnum,
            is_in_city: (address.jurisdiction_type === 'Asheville Corporate Limits'),
          };
        }),
      };
      return finalResult;
    })
    .catch((err) => {
      if (err) {
        console.log(`Got an error in searchCivicAddressID: ${JSON.stringify(err)}`);
      }
    });
};

const performSearch = function (searchString, searchContext, context) {
  if (searchContext === 'civicAddressId') {
    return searchCivicAddressId(searchString, context);
  } else if (searchContext === 'address') {
    const geolocatorUrl = 'http://192.168.0.125:6080/arcgis/rest/services/Geolocators/BC_address_unit/GeocodeServer/findAddressCandidates'
      + '?Street=&City=&ZIP='
      + `&Single+Line+Input=${encodeURIComponent(searchString)}&category=`
      + '&outFields=House%2C+PreDir%2C+StreetName%2C+SufType%2C+SubAddrUnit%2C+City%2C+ZIP'
      + '&maxLocations=&outSR=&searchExtent='
      + '&location=&distance=&magicKey=&f=pjson';
    // console.log(`Geoloc: ${geolocatorUrl}`);
    return axios.get(geolocatorUrl)
    .then(response => {
      // console.log(JSON.stringify(response.data.candidates));
      return Promise.all(response.data.candidates.map(a => {
        const pool = context.pool;
        // const myQuery = 'SELECT civicaddress_id, address_full, address_city, address_zipcode, '
        // + 'trash_pickup_day, zoning, owner_name, owner_address, owner_cityname, owner_state, '
        // + 'owner_zipcode, property_pin, property_pinext, centerline_id, jurisdiction_type '
        const myQuery = 'SELECT civicaddress_id, address_full, address_city, address_zipcode, '
        + 'address_number, address_unit, address_street_prefix, address_street_name '
        + 'FROM amd.coa_bc_address_master WHERE '
        + `address_number = '${a.attributes.House}' `
        + `AND address_unit = '${a.attributes.SubAddrUnit}' `
        + `AND address_street_prefix = '${a.attributes.PreDir}' `
        + `AND address_street_name = '${a.attributes.StreetName}' `
        + `AND address_street_type = '${a.attributes.SufType}' `
        + `AND address_commcode = '${a.attributes.City}' AND `
        + `address_zipcode = '${a.attributes.ZIP}'`;
        // console.log(`My query: ${myQuery}`);
        return pool.query(myQuery)
        .then(result => {
          // console.log(`RESULT ROWS (${result.rows.length}): ${JSON.stringify(result.rows)}`);
          return {
            items: result.rows.map(row => {
              return {
                score: a.score,
                type: 'address',
                civic_address_id: row.civicaddress_id,
                address: row.address_full,
                street_name: row.address_street_name,
                street_prefix: row.address_street_prefix,
                street_number: row.address_number,
                unit: row.address_unit,
                city: row.address_city,
                zipcode: row.address_zipcode,
                // is_in_city: row.jurisdiction_type === 'Asheville Corporate Limits',
              };
            }),
          };
        });
      }))
      .then(candidates => {
        // console.log(`Got the candidates:  ${JSON.stringify(candidates)}`);
        const result = {
          type: searchContext,
          results: candidates.reduce((prev, curr) => {
            return prev.concat(curr.items);
          }, []),
        };
        // console.log(`Final result: ${JSON.stringify(result)}`);
        return Promise.resolve(result);
      });
    })
    .catch(error => {
      console.log(error);
    });
  }
  return Promise.resolve({
    type: searchContext,
    results: [
      {
        score: 22,
        type: 'silly',
        id: 1,
        text: `search by ${searchContext}`,
      },
    ] }
  );
};
const resolvers = {
  Query: {
    search(obj, args, context) {
      const searchString = args.searchString;
      const searchContexts = args.searchContexts;
      return Promise.all(searchContexts.map((searchContext) => {
        return performSearch(searchString, searchContext, context);
      }));
    },
  },
};

module.exports = resolvers;
<commit_msg>Just did some cleanup<commit_after>const axios = require('axios');
function searchCivicAddressId(searchString, context) {
  const pool = context.pool;
  const myQuery = 'SELECT civicaddress_id, pinnum, address from coagis.bc_address'
  + `where cast(civicaddress_id as TEXT) LIKE '${searchString}%'  limit 5`;
  return pool.query(myQuery)
    .then((result) => {
      if (result.rows.length === 0) return { type: 'civicAddressId', results: [] };

      const finalResult = {
        type: 'civicAddressId',
        results: result.rows.map((address) => {
          return {
            score: 33,
            type: 'civicAddressId',
            id: address.civicaddress_id,
            civic_address_id: address.civicaddress_id,
            address: address.address,
            pinnum: address.pinnum,
            is_in_city: (address.jurisdiction_type === 'Asheville Corporate Limits'),
          };
        }),
      };
      return finalResult;
    })
    .catch((err) => {
      if (err) {
        console.log(`Got an error in searchCivicAddressID: ${JSON.stringify(err)}`);
      }
    });
}

function searchAddress(searchString, searchContext, context) {
  const geolocatorUrl = 'http://192.168.0.125:6080/arcgis/rest/services/Geolocators/BC_address_unit/GeocodeServer/findAddressCandidates'
  + '?Street=&City=&ZIP='
  + `&Single+Line+Input=${encodeURIComponent(searchString)}&category=`
  + '&outFields=House%2C+PreDir%2C+StreetName%2C+SufType%2C+SubAddrUnit%2C+City%2C+ZIP'
  + '&maxLocations=&outSR=&searchExtent='
  + '&location=&distance=&magicKey=&f=pjson';
  return axios.get(geolocatorUrl)
  .then(response => {
    // console.log(JSON.stringify(response.data.candidates));
    return Promise.all(response.data.candidates.map(a => {
      const pool = context.pool;
      // const myQuery = 'SELECT civicaddress_id, address_full, address_city, address_zipcode, '
      // + 'trash_pickup_day, zoning, owner_name, owner_address, owner_cityname, owner_state, '
      // + 'owner_zipcode, property_pin, property_pinext, centerline_id, jurisdiction_type '
      const myQuery = 'SELECT civicaddress_id, address_full, address_city, address_zipcode, '
      + 'address_number, address_unit, address_street_prefix, address_street_name '
      + 'FROM amd.coa_bc_address_master WHERE '
      + `address_number = '${a.attributes.House}' `
      + `AND address_unit = '${a.attributes.SubAddrUnit}' `
      + `AND address_street_prefix = '${a.attributes.PreDir}' `
      + `AND address_street_name = '${a.attributes.StreetName}' `
      + `AND address_street_type = '${a.attributes.SufType}' `
      + `AND address_commcode = '${a.attributes.City}' AND `
      + `address_zipcode = '${a.attributes.ZIP}'`;

      return pool.query(myQuery)
      .then(result => {
        return {
          items: result.rows.map(row => {
            return {
              score: a.score,
              type: 'address',
              civic_address_id: row.civicaddress_id,
              address: row.address_full,
              street_name: row.address_street_name,
              street_prefix: row.address_street_prefix,
              street_number: row.address_number,
              unit: row.address_unit,
              city: row.address_city,
              zipcode: row.address_zipcode,
              // is_in_city: row.jurisdiction_type === 'Asheville Corporate Limits',
            };
          }),
        };
      });
    }))
    .then(candidates => {
      const result = {
        type: 'searchContext',
        results: candidates.reduce((prev, curr) => {
          return prev.concat(curr.items);
        }, []),
      };
      return Promise.resolve(result);
    });
  })
  .catch(error => {
    throw new Error(error);
  });
}

function performSearch(searchString, searchContext, context) {
  if (searchContext === 'civicAddressId') {
    return searchCivicAddressId(searchString, context);
  } else if (searchContext === 'address') {
    return searchAddress(searchString, searchContext, context);
  }
  throw new Error(`Unknown search context ${searchContext}`);
}

const resolvers = {
  Query: {
    search(obj, args, context) {
      const searchString = args.searchString;
      const searchContexts = args.searchContexts;
      return Promise.all(searchContexts.map((searchContext) => {
        return performSearch(searchString, searchContext, context);
      }));
    },
  },
};

module.exports = resolvers;
<|endoftext|>


<commit_before>'use strict'

const common = require('./webpack.common')

const webpack = require('webpack')
const webpackTargetElectronRenderer = require('webpack-target-electron-renderer')

const config = {
  devtool: 'cheap-module-eval-source-map',
  entry: [
    'webpack-hot-middleware/client?path=http://localhost:3000/__webpack_hmr',
    ...common.entry
  ],
  output: {
    filename: common.output.filename,
    path: common.output.path,
    libraryTarget: common.output.libraryTarget,
    publicPath: 'http://localhost:3000/build/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      // TODO: This is obviously wrong for production builds.
      __DEV__: true,
      'process.env': {
        NODE_ENV: JSON.stringify('development')
      }
    })
  ],
  module: common.module,
  resolve: common.resolve,
  target: 'electron',
  externals: common.externals
}

config.target = webpackTargetElectronRenderer(config)

module.exports = config
<commit_msg>It ok now<commit_after>'use strict'

const common = require('./webpack.common')

const webpack = require('webpack')
const webpackTargetElectronRenderer = require('webpack-target-electron-renderer')

const config = {
  devtool: 'cheap-module-eval-source-map',
  entry: [
    'webpack-hot-middleware/client?path=http://localhost:3000/__webpack_hmr',
    ...common.entry
  ],
  output: {
    filename: common.output.filename,
    path: common.output.path,
    libraryTarget: common.output.libraryTarget,
    publicPath: 'http://localhost:3000/build/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      __DEV__: true,
      'process.env': {
        NODE_ENV: JSON.stringify('development')
      }
    })
  ],
  module: common.module,
  resolve: common.resolve,
  target: 'electron',
  externals: common.externals
}

config.target = webpackTargetElectronRenderer(config)

module.exports = config
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableHighlight,
  Image
} from 'react-native';
import metadataBackendProxy from './native_proxy/metadata_backend_proxy'

import loggerCreator from './utils/logger'
var moduleLogger = loggerCreator("index.android");

export default class RadioStream extends Component {
  render() {
    let logger = loggerCreator(this.render.name, moduleLogger);

    return (
      <View style={styles.container}>
        <Image source={require("./images/background.jpg")}
               style={{
                position: "absolute",
                // remove width and height to override fixed static size
                left: 0,
                right: 0,
                top: 0,
                bottom: 0,
              }}/>
        <Text style={styles.welcome}>
          Welcome to React Native!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.android.js
        </Text>
        <Text style={styles.instructions}>
          Double tap R on your keyboard to reload,{'\n'}
          Shake or press menu button for dev menu
        </Text>
        <TouchableHighlight onPress={() => {
          logger.info("fetching playlist");
          metadataBackendProxy.fetchPlaylists().then(result => {
            logger.info(result);
          })
        }} style={{
          backgroundColor: "rgba(51, 93, 102, 0.3)",
          paddingHorizontal: 40,
          paddingVertical: 10
        }}><Text style={{color: "white"}}>Temp</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('RadioStream', () => RadioStream);
<commit_msg>styling - fixed background image<commit_after>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableHighlight,
  Image
} from 'react-native';
import metadataBackendProxy from './native_proxy/metadata_backend_proxy'

import loggerCreator from './utils/logger'
var moduleLogger = loggerCreator("index.android");

export default class RadioStream extends Component {
  render() {
    let logger = loggerCreator(this.render.name, moduleLogger);

    return (
        <Image source={require("./images/background.jpg")}
               resizeMode="cover"
               style={{
                   flex: 1,
                  // remove width and height to override fixed static size
                  width: null,
                  height: null,
                  justifyContent: 'center',
                  alignItems: 'center',

        }}>
          <Text style={styles.welcome}>
            Welcome to React Native!
          </Text>
          <Text style={styles.instructions}>
            To get started, edit index.android.js
          </Text>
          <Text style={styles.instructions}>
            Double tap R on your keyboard to reload,{'\n'}
            Shake or press menu button for dev menu
          </Text>
          <TouchableHighlight onPress={() => {
          logger.info("fetching playlist");
          metadataBackendProxy.fetchPlaylists().then(result => {
            logger.info(result);
          })
        }} style={{
          backgroundColor: "rgba(51, 93, 102, 0.3)",
          paddingHorizontal: 40,
          paddingVertical: 10
        }}>
            <Text style={{color: "white"}}>Temp</Text>
          </TouchableHighlight>
        </Image>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('RadioStream', () => RadioStream);
<|endoftext|>


<commit_before>describe("Test", function () {
    "use strict";

    it("is pending");

    it("was loaded properly", function () {
        assert(true);
    });

    it("fails properly", function () {
        assert(false);
    });

    it("supports asynchronism", function (done) {
        var a = 0;
        setTimeout(function () {
            assert(a === 1);
            done();
        }, 100);
        a = 1;
    });

    it("fails asynchronously", function (done) {
        var a = 0;
        setTimeout(function () {
            assert(a === 0);
            done();
        }, 100);
        a = 1;
    });

    it("fails if done is called with a parameter", function (done) {
        setTimeout(function () {
            done("error");
        }, 100);
    });

});
<commit_msg>Adds some Eslint errors<commit_after>describe("Test", function () {
    "use strict";

    it("is pending");

    it("was loaded properly", function () {
        assert(true)
    });

    it("fails properly", function () {
        assert(false)
    });

    it("supports asynchronism", function (done) {
        var a = 0;
        setTimeout(function () {
            assert(a === 1);
            done();
        }, 100);
        a = 1;
    });

    it("fails asynchronously", function (done) {
        var a = 0;
        setTimeout(function () {
            assert(a === 0);
            done();
        }, 100);
        a = 1;
    });

    it("fails if done is called with a parameter", function (done) {
        setTimeout(function () {
            done("error");
        }, 100);
    });

});
<|endoftext|>


<commit_before>import crypto from 'crypto';
import { getConfig } from '../config';

import { parseMarkdown } from 'lib/react-utilities';

// TODO: Add Jest Testing
export function debounce(func, timeout, addInstantFlag = false) {
  /* Be careful of the addInstantFlag, as if you don't call all arguments
  of the debounced function it will append true anyway, to another argument
  than intended, and this might cause unexpected results */
  let scheduled = false;
  let lastCalled = null;
  const debouncedFunction = function(...args) {
    // eslint-disable-line func-names
    const now = new Date();
    return new Promise(resolve => {
      if (lastCalled === null || (!scheduled && now - lastCalled >= timeout)) {
        lastCalled = now;
        if (addInstantFlag) {
          // add a flag that says this function was called instantly,
          // and didn't wait for the debounce, in case you want a different
          // reaction to an instant call (for example not using state as that
          // is asynchronous and won't get the newest values)
          args.push(true);
        }
        resolve(func.apply(this, args));
      } else if (!scheduled) {
        scheduled = true;
        setTimeout(() => {
          scheduled = false;
          resolve(func.apply(this, args));
        }, timeout - (now - lastCalled));
      }
    });
  };
  return debouncedFunction;
}

export function capFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

let isClientFlag = false;

// Lets us know if we are running on server
export function isClient() {
  return isClientFlag;
}

export function setIsClient(status) {
  isClientFlag = status;
}

export function uuid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return `${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`;
}

export function mapLegacyIssueSlugsToIssueNumber(slug) {
  const match = slug.match(/issue-(\d\d)/);
  if (match) {
    return match[1];
  }
  switch (slug) {
    case 'the-identity-issue':
      return '76';
    case 'the-love-issue':
      return '78';
    case 'the-food-issue':
      return '82';
    default:
      return slug;
  }
}

// Modified from ghost/core/server/models/base.js
export function slugify(name) {
  // Remove URL reserved chars: `:/?#[]@!$&'()*+,;=` as well as `\%<>|^~£"`
  let slug = name
    .replace(/[:/?#[\]@!$&'()*+,;=\\%<>|^~£"]/g, '')
    .replace(/(\s|\.)/g, '-')
    .replace(/-+/g, '-')
    .toLowerCase();

  while (slug.charAt(slug.length - 1) === '-') {
    slug = slug.substr(0, slug.length - 1);
  }
  return slug;
}

// this currently only supports parsing links
export function markdownLength(str) {
  if (!str) return 0;
  const array = parseMarkdown(str);
  let length = 0;
  array.forEach(element => {
    if (typeof element === 'string') {
      length += element.length;
    } else {
      // assume it is a link
      length += element.props.children.length;
    }
  });
  return length;
}

export function hash(password) {
  const hashInstance = crypto.createHash('sha512');
  return hashInstance.update(password).digest('hex');
}

// For tracking the articles visited in that particular session
// so we at least don't count views more than once per session
const viewed = {};
export function viewArticle(slug) {
  viewed[slug] = true;
}

export function isArticleViewed(slug) {
  return viewed[slug] === true;
}

export function followPath(path, object) {
  /*
  Returns the value at the end of a path at a given object
  */

  // If using dot notation obj.key.key.key
  let processedPath = path;
  if (typeof path === 'string') {
    processedPath = path.split('.');
  }
  return processedPath.reduce((currentObject, nextChild) => {
    if (currentObject !== undefined && has.call(currentObject, nextChild)) {
      return currentObject[nextChild];
    }

    return undefined;
  }, object);
}

export function isPlainObject(element) {
  // Handle getPrototypeOf throwing error on undefined or null
  if (!element) {
    return false;
  }
  return Object.getPrototypeOf(element) === Object.prototype;
}

/**
 * Taken from https://stackoverflow.com/questions/767486/how-do-you-check-if-a-variable-is-an-array-in-javascript
 * @param {any} candidate
 * @returns {boolean}
 */
export function isArray(candidate) {
  return candidate.constructor === Array;
}

/**
 * Taken from https://stackoverflow.com/questions/5999998/how-can-i-check-if-a-javascript-variable-is-function-type
 * @param {any} candidate
 * @returns {boolean}
 */
export function isFunction(candidate) {
  return typeof candidate === 'function';
}

export function stringToInt(str) {
  if (/^[0-9]+$/.test(str)) {
    return parseInt(str, 10);
  }
  return NaN;
}

export const has = Object.prototype.hasOwnProperty;

// Environment functions and constants
export const isProduction = () => getConfig().NODE_ENV === 'production';
export const isStaging = () => getConfig().NODE_ENV === 'staging';
export const isCI = () => getConfig().GAZELLE_ENV === 'CI';
export const isDevelopment = () => !isProduction() && !isStaging();

export function filterByEnvironment(development, beta, production) {
  if (production === undefined) {
    /**
     * In case of only two arguments being specificed we re-value the arguments
     * so they now function as non-production and production
     */
    if (development === undefined || beta === undefined) {
      // Less than 2 arguments were given which is not supported
      throw new Error(
        'Less than 2 arguments were passed to filterByEnvironment',
      );
    }

    if (isProduction()) {
      return beta;
    }
    return development;
  }

  // All 3 arguments were specified
  if (isProduction()) {
    return production;
  } else if (isStaging()) {
    return beta;
  }
  return development;
}

export const nothingAllowedRobotsTxt = 'User-agent: *\nDisallow: /\n';

export const googleClientID =
  '235485701704-vqb1qkp8lk1hbdhcmjm5jmtocaur3mq7.apps.googleusercontent.com';
export const googleWhitelist = [
  'jmp907@nyu.edu',
  'mm7969@nyu.edu',
  'ego225@nyu.edu',
  'ns3774@nyu.edu',
  'yt1289@nyu.edu',
  'jhe251@nyu.edu',
  'pet240@nyu.edu',
];
<commit_msg>Update admins<commit_after>import crypto from 'crypto';
import { getConfig } from '../config';

import { parseMarkdown } from 'lib/react-utilities';

// TODO: Add Jest Testing
export function debounce(func, timeout, addInstantFlag = false) {
  /* Be careful of the addInstantFlag, as if you don't call all arguments
  of the debounced function it will append true anyway, to another argument
  than intended, and this might cause unexpected results */
  let scheduled = false;
  let lastCalled = null;
  const debouncedFunction = function(...args) {
    // eslint-disable-line func-names
    const now = new Date();
    return new Promise(resolve => {
      if (lastCalled === null || (!scheduled && now - lastCalled >= timeout)) {
        lastCalled = now;
        if (addInstantFlag) {
          // add a flag that says this function was called instantly,
          // and didn't wait for the debounce, in case you want a different
          // reaction to an instant call (for example not using state as that
          // is asynchronous and won't get the newest values)
          args.push(true);
        }
        resolve(func.apply(this, args));
      } else if (!scheduled) {
        scheduled = true;
        setTimeout(() => {
          scheduled = false;
          resolve(func.apply(this, args));
        }, timeout - (now - lastCalled));
      }
    });
  };
  return debouncedFunction;
}

export function capFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

let isClientFlag = false;

// Lets us know if we are running on server
export function isClient() {
  return isClientFlag;
}

export function setIsClient(status) {
  isClientFlag = status;
}

export function uuid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return `${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`;
}

export function mapLegacyIssueSlugsToIssueNumber(slug) {
  const match = slug.match(/issue-(\d\d)/);
  if (match) {
    return match[1];
  }
  switch (slug) {
    case 'the-identity-issue':
      return '76';
    case 'the-love-issue':
      return '78';
    case 'the-food-issue':
      return '82';
    default:
      return slug;
  }
}

// Modified from ghost/core/server/models/base.js
export function slugify(name) {
  // Remove URL reserved chars: `:/?#[]@!$&'()*+,;=` as well as `\%<>|^~£"`
  let slug = name
    .replace(/[:/?#[\]@!$&'()*+,;=\\%<>|^~£"]/g, '')
    .replace(/(\s|\.)/g, '-')
    .replace(/-+/g, '-')
    .toLowerCase();

  while (slug.charAt(slug.length - 1) === '-') {
    slug = slug.substr(0, slug.length - 1);
  }
  return slug;
}

// this currently only supports parsing links
export function markdownLength(str) {
  if (!str) return 0;
  const array = parseMarkdown(str);
  let length = 0;
  array.forEach(element => {
    if (typeof element === 'string') {
      length += element.length;
    } else {
      // assume it is a link
      length += element.props.children.length;
    }
  });
  return length;
}

export function hash(password) {
  const hashInstance = crypto.createHash('sha512');
  return hashInstance.update(password).digest('hex');
}

// For tracking the articles visited in that particular session
// so we at least don't count views more than once per session
const viewed = {};
export function viewArticle(slug) {
  viewed[slug] = true;
}

export function isArticleViewed(slug) {
  return viewed[slug] === true;
}

export function followPath(path, object) {
  /*
  Returns the value at the end of a path at a given object
  */

  // If using dot notation obj.key.key.key
  let processedPath = path;
  if (typeof path === 'string') {
    processedPath = path.split('.');
  }
  return processedPath.reduce((currentObject, nextChild) => {
    if (currentObject !== undefined && has.call(currentObject, nextChild)) {
      return currentObject[nextChild];
    }

    return undefined;
  }, object);
}

export function isPlainObject(element) {
  // Handle getPrototypeOf throwing error on undefined or null
  if (!element) {
    return false;
  }
  return Object.getPrototypeOf(element) === Object.prototype;
}

/**
 * Taken from https://stackoverflow.com/questions/767486/how-do-you-check-if-a-variable-is-an-array-in-javascript
 * @param {any} candidate
 * @returns {boolean}
 */
export function isArray(candidate) {
  return candidate.constructor === Array;
}

/**
 * Taken from https://stackoverflow.com/questions/5999998/how-can-i-check-if-a-javascript-variable-is-function-type
 * @param {any} candidate
 * @returns {boolean}
 */
export function isFunction(candidate) {
  return typeof candidate === 'function';
}

export function stringToInt(str) {
  if (/^[0-9]+$/.test(str)) {
    return parseInt(str, 10);
  }
  return NaN;
}

export const has = Object.prototype.hasOwnProperty;

// Environment functions and constants
export const isProduction = () => getConfig().NODE_ENV === 'production';
export const isStaging = () => getConfig().NODE_ENV === 'staging';
export const isCI = () => getConfig().GAZELLE_ENV === 'CI';
export const isDevelopment = () => !isProduction() && !isStaging();

export function filterByEnvironment(development, beta, production) {
  if (production === undefined) {
    /**
     * In case of only two arguments being specificed we re-value the arguments
     * so they now function as non-production and production
     */
    if (development === undefined || beta === undefined) {
      // Less than 2 arguments were given which is not supported
      throw new Error(
        'Less than 2 arguments were passed to filterByEnvironment',
      );
    }

    if (isProduction()) {
      return beta;
    }
    return development;
  }

  // All 3 arguments were specified
  if (isProduction()) {
    return production;
  } else if (isStaging()) {
    return beta;
  }
  return development;
}

export const nothingAllowedRobotsTxt = 'User-agent: *\nDisallow: /\n';

export const googleClientID =
  '235485701704-vqb1qkp8lk1hbdhcmjm5jmtocaur3mq7.apps.googleusercontent.com';
export const googleWhitelist = [
  'jmp907@nyu.edu',
  'mm7969@nyu.edu',
  'ego225@nyu.edu',
  'ns3774@nyu.edu',
  'yt1289@nyu.edu',
  'jhe251@nyu.edu',
  'pet240@nyu.edu',
  'an2713@nyu.edu',
];
<|endoftext|>