<commit_before>const path = require('path');
const electron = require('electron');
const {
  loadPlugins,
  queryResults,
  connectItems,
} = require('./plugins');
const { loadTheme } = require('./themes');
const {
  IPC_WINDOW_SHOW,
  IPC_WINDOW_HIDE,
  IPC_WINDOW_RESIZE,
  IPC_WINDOW_COLLAPSE,
  IPC_QUERY_COMMAND,
  IPC_QUERY_RESULTS,
  IPC_SELECT_PREVIOUS_ITEM,
  IPC_SELECT_NEXT_ITEM,
  IPC_EXECUTE_CURRENT_ITEM,
  IPC_EXECUTE_ITEM,
  IPC_LOAD_THEME,
} = require('../ipc');
const Config = require('../../utils/conf');
const { debounce } = require('../../utils/helpers');

const { app, BrowserWindow, globalShortcut, ipcMain, shell } = electron;

// set default window values
const WINDOW_DEFAULT_WIDTH = 650;
const WINDOW_DEFAULT_HEIGHT = 80;
const WINDOW_MIN_HEIGHT = 80;
const WINDOW_MAX_HEIGHT = 680; // results + query
const MAX_RESULTS = 20;

let win = null;

// create a user config
const config = new Config();

const hideWindow = () => {
  win && win.hide();
  return undefined;
};

// toggles the main window visibility
const toggleMainWindow = () => {
  if (win.isVisible()) {
    hideWindow();
  } else {
    win.show();
  }
};

const execute = message => {
  switch (message.action) {
    case 'openurl':
      if (message.item.arg) {
        shell.openExternal(message.item.arg);
      }
      break;
    default:
      // do nothing
      break;
  }
};

const selectPreviousItem = () => {
  win.webContents.send(IPC_SELECT_PREVIOUS_ITEM);
};

const selectNextItem = () => {
  win.webContents.send(IPC_SELECT_NEXT_ITEM);
};

const executeCurrentItem = () => {
  win.webContents.send(IPC_EXECUTE_CURRENT_ITEM);
};

const repositionWindow = () => {
  const { screen } = electron;
  const cursorPoint = screen.getCursorScreenPoint();
  const currScreen = screen.getDisplayNearestPoint(cursorPoint);
  const resultsHeight = WINDOW_MAX_HEIGHT;
  const size = win.getSize();
  const winPosition = [
    ((currScreen.size.width / 2) - (size[0] / 2)) + currScreen.bounds.x,
    ((currScreen.size.height / 2) - ((size[1] + resultsHeight) / 2)) + currScreen.bounds.y,
  ];
  win.setPosition(winPosition[0], winPosition[1]);
};

// free the window object from memory
const handleWindowClose = () => {
  win = null;
};

const handleWindowShow = () => {
  globalShortcut.register('up', selectPreviousItem);
  globalShortcut.register('down', selectNextItem);
  globalShortcut.register('enter', executeCurrentItem);
  win.webContents.send(IPC_WINDOW_SHOW);
};

const handleWindowHide = () => {
  globalShortcut.unregister('up');
  globalShortcut.unregister('down');
  globalShortcut.unregister('enter');
  win.webContents.send(IPC_WINDOW_HIDE);
};

const handleWindowBlur = () => {
  win.hide();
};

const handleWindowResize = (evt, { width, height }) => {
  // re-size
  const size = win.getContentSize();
  const newWidth = width || size[0];
  const newHeight = (WINDOW_MIN_HEIGHT + height) || size[1];
  win.setContentSize(newWidth, newHeight);
};

const handleWindowCollapse = () => {
  const size = win.getContentSize();
  win.setContentSize(size[0], WINDOW_MIN_HEIGHT);
};

/**
 * Loads the theme when the finish has finished loading
 */
const handleDidFinishLoad = () => {
  const t = config.get('theme') || '';
  loadTheme(t).then(theme => {
    if (theme) {
      win.webContents.send(IPC_LOAD_THEME, theme);
    }
    // initial window display
    win.show();
  });
};

/**
 * Makes a query to all plugins.
 *
 * plugins { path, name, isCore, schema, action, keyword }
 *
 * @param {Event} evt
 * @param {Object} message - The IPC message { q, type }
 * @param {Object[]} plugins - An array of plugin objects
 */
const handleQueryCommand = (evt, message, plugins) => {
  let args = message.q.split(' ');
  const kw = args.shift().toLowerCase();
  // collect results
  const results = [];
  // find if it matches the current keyword
  const matchedPlugins = plugins.filter(p => kw.length && kw === p.keyword.toLowerCase());
  // if plugins are found with the current keyword
  // only make queries to those plugins
  if (matchedPlugins && matchedPlugins.length) {
    // if no args are set, display the keyword helper
    if (!args.length || !args[0].trim().length) {
      // retrieve the helper item
      // call if it's a function
      // and resolve as necessary
      const helper = matchedPlugins[0].helper;
      let helperItem = helper;
      if (typeof helper === 'function') {
        helperItem = helper(kw);
      }
      Promise.resolve(helperItem).then(item => {
        // send a result for the current filtered keyword
        evt.sender.send(IPC_QUERY_RESULTS, connectItems([item], matchedPlugins[0]));
      });
    } else {
      matchedPlugins.forEach(plugin => {
        results.push(queryResults(plugin, args));
      });
    }
  } else {
    // otherwise, do a regular query
    plugins.forEach(plugin => {
      // make sure to reset the args array for each plugin
      args = message.q.split(' ');
      // if core, then just apply the output method
      if (plugin.isCore) {
        results.push(queryResults(plugin, args));
      } else {
        // extract the keyword
        const keyword = args.shift();
        // if the keyword exists and query matches the plugin's keyword
        if (keyword && plugin.keyword.toLowerCase() === keyword.toLowerCase()) {
          results.push(queryResults(plugin, args));
        }
      }
    });
  }
  Promise.all(results).then(resultSet => {
    const retval = resultSet
      // flatten and merge items
      .reduce((prev, next) => prev.concat(next))
      // filter max results
      .slice(0, MAX_RESULTS);
    // send the results back to the renderer
    evt.sender.send(IPC_QUERY_RESULTS, retval || []);
  });
};

/**
 * Create a debounced function for handling the query command
 */
const debounceHandleQueryCommand = debounce(handleQueryCommand, 500);

/**
 * Creates a new Browser window and loads the renderer index
 */
const createWindow = () => {
  win = new BrowserWindow({
    width: WINDOW_DEFAULT_WIDTH,
    height: WINDOW_DEFAULT_HEIGHT,
    maxHeight: WINDOW_MAX_HEIGHT,
    center: false,
    frame: false,
    show: false,
    minimizable: false,
    maximizable: false,
    hasShadow: true,
    skipTaskbar: true,
  });

  // re-position
  repositionWindow();

  const rendererPath = path.resolve(__dirname, '..', 'renderer');
  const indexPath = `file://${rendererPath}/index.html`;

  win.loadURL(indexPath);

  win.on('closed', handleWindowClose);
  win.on('show', handleWindowShow);
  win.on('hide', handleWindowHide);
  win.on('blur', handleWindowBlur);
  win.webContents.on('did-finish-load', handleDidFinishLoad);

  // expand and collapse window based on the results
  ipcMain.on(IPC_WINDOW_RESIZE, handleWindowResize);
  ipcMain.on(IPC_WINDOW_COLLAPSE, handleWindowCollapse);

  // register global shortcuts
  globalShortcut.register('cmd+space', toggleMainWindow);
  globalShortcut.register('escape', hideWindow);

  /**
   * Registers the query command listeners for all plugins
   *
   * { path, name, isCore, schema, action, keyword }
   *
   * @param {Object[]} plugins - An array of plugin objects
   */
  const registerIpcListeners = plugins => {
    // listen to query commands and queries
    // for results and sends it to the renderer
    ipcMain.on(IPC_QUERY_COMMAND, (evt, message) => debounceHandleQueryCommand(evt, message, plugins));
    // listen for execution commands
    ipcMain.on(IPC_EXECUTE_ITEM, (evt, message) => {
      execute(message);
    });
  };

  // load all plugins and then
  // registers the ipc listeners
  loadPlugins().then(plugins => {
    registerIpcListeners(plugins);
  });
};

app.on('ready', createWindow);
<commit_msg>chore(handleBlur): map handleBlur to hideWindow<commit_after>const path = require('path');
const electron = require('electron');
const {
  loadPlugins,
  queryResults,
  connectItems,
} = require('./plugins');
const { loadTheme } = require('./themes');
const {
  IPC_WINDOW_SHOW,
  IPC_WINDOW_HIDE,
  IPC_WINDOW_RESIZE,
  IPC_WINDOW_COLLAPSE,
  IPC_QUERY_COMMAND,
  IPC_QUERY_RESULTS,
  IPC_SELECT_PREVIOUS_ITEM,
  IPC_SELECT_NEXT_ITEM,
  IPC_EXECUTE_CURRENT_ITEM,
  IPC_EXECUTE_ITEM,
  IPC_LOAD_THEME,
} = require('../ipc');
const Config = require('../../utils/conf');
const { debounce } = require('../../utils/helpers');

const { app, BrowserWindow, globalShortcut, ipcMain, shell } = electron;

// set default window values
const WINDOW_DEFAULT_WIDTH = 650;
const WINDOW_DEFAULT_HEIGHT = 80;
const WINDOW_MIN_HEIGHT = 80;
const WINDOW_MAX_HEIGHT = 680; // results + query
const MAX_RESULTS = 20;

let win = null;

// create a user config
const config = new Config();

const hideWindow = () => {
  win && win.hide();
  return undefined;
};

// toggles the main window visibility
const toggleMainWindow = () => {
  if (win.isVisible()) {
    hideWindow();
  } else {
    win.show();
  }
};

const execute = message => {
  switch (message.action) {
    case 'openurl':
      if (message.item.arg) {
        shell.openExternal(message.item.arg);
      }
      break;
    default:
      // do nothing
      break;
  }
};

const selectPreviousItem = () => {
  win.webContents.send(IPC_SELECT_PREVIOUS_ITEM);
};

const selectNextItem = () => {
  win.webContents.send(IPC_SELECT_NEXT_ITEM);
};

const executeCurrentItem = () => {
  win.webContents.send(IPC_EXECUTE_CURRENT_ITEM);
};

const repositionWindow = () => {
  const { screen } = electron;
  const cursorPoint = screen.getCursorScreenPoint();
  const currScreen = screen.getDisplayNearestPoint(cursorPoint);
  const resultsHeight = WINDOW_MAX_HEIGHT;
  const size = win.getSize();
  const winPosition = [
    ((currScreen.size.width / 2) - (size[0] / 2)) + currScreen.bounds.x,
    ((currScreen.size.height / 2) - ((size[1] + resultsHeight) / 2)) + currScreen.bounds.y,
  ];
  win.setPosition(winPosition[0], winPosition[1]);
};

// free the window object from memory
const handleWindowClose = () => {
  win = null;
};

const handleWindowShow = () => {
  globalShortcut.register('up', selectPreviousItem);
  globalShortcut.register('down', selectNextItem);
  globalShortcut.register('enter', executeCurrentItem);
  win.webContents.send(IPC_WINDOW_SHOW);
};

const handleWindowHide = () => {
  globalShortcut.unregister('up');
  globalShortcut.unregister('down');
  globalShortcut.unregister('enter');
  win.webContents.send(IPC_WINDOW_HIDE);
};

const handleWindowBlur = hideWindow;

const handleWindowResize = (evt, { width, height }) => {
  // re-size
  const size = win.getContentSize();
  const newWidth = width || size[0];
  const newHeight = (WINDOW_MIN_HEIGHT + height) || size[1];
  win.setContentSize(newWidth, newHeight);
};

const handleWindowCollapse = () => {
  const size = win.getContentSize();
  win.setContentSize(size[0], WINDOW_MIN_HEIGHT);
};

/**
 * Loads the theme when the finish has finished loading
 */
const handleDidFinishLoad = () => {
  const t = config.get('theme') || '';
  loadTheme(t).then(theme => {
    if (theme) {
      win.webContents.send(IPC_LOAD_THEME, theme);
    }
    // initial window display
    win.show();
  });
};

/**
 * Makes a query to all plugins.
 *
 * plugins { path, name, isCore, schema, action, keyword }
 *
 * @param {Event} evt
 * @param {Object} message - The IPC message { q, type }
 * @param {Object[]} plugins - An array of plugin objects
 */
const handleQueryCommand = (evt, message, plugins) => {
  let args = message.q.split(' ');
  const kw = args.shift().toLowerCase();
  // collect results
  const results = [];
  // find if it matches the current keyword
  const matchedPlugins = plugins.filter(p => kw.length && kw === p.keyword.toLowerCase());
  // if plugins are found with the current keyword
  // only make queries to those plugins
  if (matchedPlugins && matchedPlugins.length) {
    // if no args are set, display the keyword helper
    if (!args.length || !args[0].trim().length) {
      // retrieve the helper item
      // call if it's a function
      // and resolve as necessary
      const helper = matchedPlugins[0].helper;
      let helperItem = helper;
      if (typeof helper === 'function') {
        helperItem = helper(kw);
      }
      Promise.resolve(helperItem).then(item => {
        // send a result for the current filtered keyword
        evt.sender.send(IPC_QUERY_RESULTS, connectItems([item], matchedPlugins[0]));
      });
    } else {
      matchedPlugins.forEach(plugin => {
        results.push(queryResults(plugin, args));
      });
    }
  } else {
    // otherwise, do a regular query
    plugins.forEach(plugin => {
      // make sure to reset the args array for each plugin
      args = message.q.split(' ');
      // if core, then just apply the output method
      if (plugin.isCore) {
        results.push(queryResults(plugin, args));
      } else {
        // extract the keyword
        const keyword = args.shift();
        // if the keyword exists and query matches the plugin's keyword
        if (keyword && plugin.keyword.toLowerCase() === keyword.toLowerCase()) {
          results.push(queryResults(plugin, args));
        }
      }
    });
  }
  Promise.all(results).then(resultSet => {
    const retval = resultSet
      // flatten and merge items
      .reduce((prev, next) => prev.concat(next))
      // filter max results
      .slice(0, MAX_RESULTS);
    // send the results back to the renderer
    evt.sender.send(IPC_QUERY_RESULTS, retval || []);
  });
};

/**
 * Create a debounced function for handling the query command
 */
const debounceHandleQueryCommand = debounce(handleQueryCommand, 500);

/**
 * Creates a new Browser window and loads the renderer index
 */
const createWindow = () => {
  win = new BrowserWindow({
    width: WINDOW_DEFAULT_WIDTH,
    height: WINDOW_DEFAULT_HEIGHT,
    maxHeight: WINDOW_MAX_HEIGHT,
    center: false,
    frame: false,
    show: false,
    minimizable: false,
    maximizable: false,
    hasShadow: true,
    skipTaskbar: true,
  });

  // re-position
  repositionWindow();

  const rendererPath = path.resolve(__dirname, '..', 'renderer');
  const indexPath = `file://${rendererPath}/index.html`;

  win.loadURL(indexPath);

  win.on('closed', handleWindowClose);
  win.on('show', handleWindowShow);
  win.on('hide', handleWindowHide);
  win.on('blur', handleWindowBlur);
  win.webContents.on('did-finish-load', handleDidFinishLoad);

  // expand and collapse window based on the results
  ipcMain.on(IPC_WINDOW_RESIZE, handleWindowResize);
  ipcMain.on(IPC_WINDOW_COLLAPSE, handleWindowCollapse);

  // register global shortcuts
  globalShortcut.register('cmd+space', toggleMainWindow);
  globalShortcut.register('escape', hideWindow);

  /**
   * Registers the query command listeners for all plugins
   *
   * { path, name, isCore, schema, action, keyword }
   *
   * @param {Object[]} plugins - An array of plugin objects
   */
  const registerIpcListeners = plugins => {
    // listen to query commands and queries
    // for results and sends it to the renderer
    ipcMain.on(IPC_QUERY_COMMAND, (evt, message) => debounceHandleQueryCommand(evt, message, plugins));
    // listen for execution commands
    ipcMain.on(IPC_EXECUTE_ITEM, (evt, message) => {
      execute(message);
    });
  };

  // load all plugins and then
  // registers the ipc listeners
  loadPlugins().then(plugins => {
    registerIpcListeners(plugins);
  });
};

app.on('ready', createWindow);
<|endoftext|>


<commit_before>// NPM Modules
import meow     from 'meow';
import stdin    from 'get-stdin';
import textr    from 'textr';

// Native Modules
import path     from 'path';
import fs       from 'fs';

/**
 * CLI app instance of Meow
 * More: https://www.npmjs.com/package/meow
 * @param  {Object|Array|String} Text that will be write on --help or -h
 * @param  {Object}              Minimist options (github.com/substack/minimist)
 * @return {Object}              A Meow CLI helper object
 */
const cli = meow(`
  Usage
    $ textr

  Options
    -t, --transforms    Array of transformers
    -h, --help          Show this message
    -o, --out-file      Write output to file

  Examples
    $ textr foo.md -t typographic-quotes -t typographic-quotes
    $ textr foo.md -t typographic-single-spaces,typographic-quotes
    $ cat foo.md | textr --transforms=typographic-single-spaces
    $ cat foo.md | textr -o bar.md
`,
  {
    default: {
      transforms: [],
    },
    alias: {
      o: 'out-file',
      t: 'transforms',
      h: 'help'
    }
  }
);

/**
 * Resolve file name with current dir
 * @param  {String} file Any relative filename
 * @return {String}      Resolved path to file
 */
const cwd = file =>
  path.resolve(process.cwd(), file);

/**
 * Render text string throught textr transformer
 * @param  {String} text Text that will be processed
 * @param  {Array}  tfs  Array of transformers
 * @return {Void}        Write into strout or file and exit
 */
const render = (text, tfs = []) => {
  const res = (textr().use.apply(null, tfs))(text);
  if (cli.flags.outFile) {
    try {
      fs.writeFileSync(cwd(cli.flags.outFile), res, 'utf8');
    } catch (e) {
      console.error(`Something went wrong: ${e.message}`);
      process.exit(1);
    }
  } else {
    process.stdout.write(res);
    process.exit(0);
  }
};

/**
 * Get array of transformers.
 * If list of transformers is a string, then split it.
 * After all, require everything.
 * @param  {String|Array} t String or Array that contains list of transformers
 * @return {Array}          Return array of transform functions
 */
const tfs = (t = cli.flags.transforms) =>
  (typeof t === 'string' ? t.split(',') : t).map(tf => require(tf));

/**
 * Entry point
 */
if (cli.input[0]) {
  // If there is first argument, then read this file
  render(
    fs.readFileSync(cwd(cli.input[0])).toString(),
    tfs()
  );
} else {
  // If there's no first argument, then try to read stdin
  stdin()
    .then(str => render(str, tfs()))
    .catch(err => err);
}
<commit_msg>Wrap reading file in try..catch.<commit_after>// NPM Modules
import meow     from 'meow';
import stdin    from 'get-stdin';
import textr    from 'textr';

// Native Modules
import path     from 'path';
import fs       from 'fs';

/**
 * CLI app instance of Meow
 * More: https://www.npmjs.com/package/meow
 * @param  {Object|Array|String} Text that will be write on --help or -h
 * @param  {Object}              Minimist options (github.com/substack/minimist)
 * @return {Object}              A Meow CLI helper object
 */
const cli = meow(`
  Usage
    $ textr

  Options
    -t, --transforms    Array of transformers
    -h, --help          Show this message
    -o, --out-file      Write output to file

  Examples
    $ textr foo.md -t typographic-quotes -t typographic-quotes
    $ textr foo.md -t typographic-single-spaces,typographic-quotes
    $ cat foo.md | textr --transforms=typographic-single-spaces
    $ cat foo.md | textr -o bar.md
`,
  {
    default: {
      transforms: [],
    },
    alias: {
      o: 'out-file',
      t: 'transforms',
      h: 'help'
    }
  }
);

/**
 * Resolve file name with current dir
 * @param  {String} file Any relative filename
 * @return {String}      Resolved path to file
 */
const cwd = file =>
  path.resolve(process.cwd(), file);

/**
 * Render text string throught textr transformer
 * @param  {String} text Text that will be processed
 * @param  {Array}  tfs  Array of transformers
 * @return {Void}        Write into strout or file and exit
 */
const render = (text, tfs = []) => {
  const res = (textr().use.apply(null, tfs))(text);
  if (cli.flags.outFile) {
    try {
      fs.writeFileSync(cwd(cli.flags.outFile), res, 'utf8');
    } catch (e) {
      console.error(`Something went wrong: ${e.message}`);
      process.exit(1);
    }
  } else {
    process.stdout.write(res);
    process.exit(0);
  }
};

/**
 * Get array of transformers.
 * If list of transformers is a string, then split it.
 * After all, require everything.
 * @param  {String|Array} t String or Array that contains list of transformers
 * @return {Array}          Return array of transform functions
 */
const tfs = (t = cli.flags.transforms) =>
  (typeof t === 'string' ? t.split(',') : t).map(tf => require(tf));

/**
 * Entry point
 */
if (cli.input[0]) {
  // If there is first argument, then read this file
  try {
    render(
      fs.readFileSync(cwd(cli.input[0])).toString(),
      tfs()
    );
  } catch (e) {
    console.error(`Something went wrong: ${e.message}`);
    process.exit(1);
  }
} else {
  // If there's no first argument, then try to read stdin
  stdin()
    .then(str => render(str, tfs()))
    .catch(err => err);
}
<|endoftext|>


<commit_before>// Use this file to change prototype configuration.

// Note: prototype config can be overridden using environment variables (eg on heroku)

module.exports = {

  // Service name used in header. Eg: 'Renew your passport'
  serviceName: "Medicines Information Alpha",

  // Default port that prototype runs on
  port: '3000',

  // Enable or disable password protection on production
  useAuth: 'true'

};
<commit_msg>:memo: Rebased with master<commit_after>// Use this file to change prototype configuration.

// Note: prototype config can be overridden using environment variables (eg on heroku)

module.exports = {

  // Service name used in header. Eg: 'Renew your passport'
  serviceName: "Medicines Information Alpha",

  // Default port that prototype runs on
  port: '3000',

  // Enable or disable password protection on production
  useAuth: 'false'

};
<|endoftext|>


<commit_before>importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js')

if (workbox) {
  workbox.precaching.precacheAndRoute([
    { url: '/index.html', revision: '2020.Jul.02-1' },
    { url: '/main.min.css', revision: '2020.Jul.02-1' },
    { url: '/manifest.json', revision: '2020.Jul.01' },
  ])

  const handler = workbox.precaching.createHandlerBoundToURL('/index.html')
  const navigationRoute = new workbox.routing.NavigationRoute(handler)
  const defaultStrategy = new workbox.strategies.StaleWhileRevalidate()

  workbox.routing.registerRoute(navigationRoute)
  workbox.routing.setDefaultHandler(args => {
    if (args.event.request.method === 'GET') {
      return defaultStrategy.handle(args)
    }
    return fetch(args.event.request)
  })
}
<commit_msg>Update sw.js<commit_after>importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js')

if (workbox) {
  workbox.precaching.precacheAndRoute([
    { url: '/index.html', revision: '2020.Jul.08' },
    { url: '/main.min.css', revision: '2020.Jul.02-1' },
    { url: '/manifest.json', revision: '2020.Jul.01' },
  ])

  const handler = workbox.precaching.createHandlerBoundToURL('/index.html')
  const navigationRoute = new workbox.routing.NavigationRoute(handler)
  const defaultStrategy = new workbox.strategies.StaleWhileRevalidate()

  workbox.routing.registerRoute(navigationRoute)
  workbox.routing.setDefaultHandler(args => {
    if (args.event.request.method === 'GET') {
      return defaultStrategy.handle(args)
    }
    return fetch(args.event.request)
  })
}
<|endoftext|>


<commit_before>// HN VImmy Bot
// Mike P Land
// Every Hour Scans Hacker News For Stories on Vim and Tweets Them, see mikepland.com/hn_vimmy_bot
// Script is being run with Crontab, ($ crontab -e)

var request = require("request")
var Twitter = require("twitter")
var googl = require('goo.gl');
var async = require('async');
var util = require('util');
var admin = require("firebase-admin");

var chatEmoji = '💬';
var linkEmoji = '🔗';

// Set a developer key (_required by Google_; see http://goo.gl/4DvFk for more info.)
googl.setKey(process.env.hn_vimmy_bot_google_api_key);

// Get currently set developer key
googl.getKey();

var client = new Twitter({
    consumer_key: process.env.twitter_kotlin_consumer_key,
    consumer_secret: process.env.twitter_kotlin_consumer_secret,
    access_token_key: process.env.twitter_kotlin_access_token_key,
    access_token_secret: process.env.twitter_kotlin_access_token_secret
});

admin.initializeApp({
    credential: admin.credential.cert("./config/hnbot-8bb67-firebase-adminsdk-rszpo-c0cd32c24f.json"),
    databaseURL: "https://hnbot-8bb67.firebaseio.com/"
});

var db = admin.database();
var ref = db.ref("/bots");

function grabDBSnapshot(callback) {
    console.log("Taking DB Snapshot");
    ref.on("value", function(snapshot) {
        console.log("Successfully got DB Snapshot");
        ref.off();
        callback(snapshot.val());
    }, function (errorObject) {
        console.log("The read failed: " + errorObject.code);
        process.exit(1);
    });
};

function saveNewStory(botPWD, savePackage, saveCallback) {
    console.log("Saving User Infomation To Database");
    ref.child(botPWD).update(savePackage).then(function() {
        console.log("Successfully Saved Story Info to Database");
        saveCallback();
    }).catch(function(error) {
        console.log("Firebase Error: " + error);
        process.exit(1);
        saveCallback();
    });
}

// Async makes sure to keep callback straight
var q = async.queue(function (task, finalCallback) {
    async.waterfall([
            function(mainCallback) {
                request(task.url, function(err, res, body) {
                    if (err) {
                        console.log(util.inspect("Error in fetchStory " + err, false, null));
                        finalCallback();
                    } else if (res.statusCode != 200) {
                        console.log(util.inspect("Error in fetchStory response not 200 " + res.statusCode, false, null));
                        finalCallback();
                    } else {
                        mainCallback(null, body)
                    }
                });
            },
            function(body, mainCallback) {
                var storyActualJSON = JSON.parse(body);

                console.log("Found story: " + storyActualJSON.title);

                // check title for stories with "kotlin" in the title
                if (storyActualJSON.title.match(/Kotlin\b/gi)) {
                    // shorten HN Link
                    console.log("Found story on VIM: " + storyActualJSON.title);
                    console.log("Shortening HN Discussion Link");
                    googl.shorten('https://news.ycombinator.com/item?id=' + storyActualJSON.id)
                        .then(function (shortUrl) {
                            // Shorten Story Link
                            console.log("Link Successfully Shortened");
                            mainCallback(null, storyActualJSON, shortUrl);
                        })
                    .catch(function (err) {
                        console.log(util.inspect("Hacker News Link Error: " + err, false, null));
                        finalCallback();
                    });
                } else {
                    // console.log("no match for " + storyActualJSON.title)
                    finalCallback();
                }

            },
            function(storyActualJSON, hnLink, mainCallback) {
                console.log("Checking to see if story is \"ASK HN:\"");
                // check to see if post is "Ask HN:" and thus no story link
                if (storyActualJSON.url == undefined) {
                    var outgoingTweet = storyActualJSON.title + "\n" + chatEmoji + ": " + hnLink + "\n#HackerNews #Kotlin";
                    mainCallback(null, outgoingTweet);
                } else {
                    console.log("Shortening Story Link");
                    googl.shorten(storyActualJSON.url)
                        .then(function (shortUrl) {
                            console.log("Successfully Shortened Story Link");
                            var outgoingTweet = storyActualJSON.title + "\n" + chatEmoji + " " + hnLink + "\n" + linkEmoji + " " + shortUrl + "\n#HackerNews #VIM";
                            mainCallback(null, outgoingTweet)
                        })
                    .catch(function (err) {
                        console.log(util.inspect("Story Link Error: " + err, false, null));
                        // sendDMErrorMessage(error);
                        finalCallback();
                    });
                }
            },
            function(outgoingTweet, mainCallback) {
                console.error("Tweeting out Story");
                client.post('statuses/update', {status: outgoingTweet},  function(error, tweet, response){
                    if (!error && response.statusCode === 200) {
                        console.log("Just Successfully Tweeted");
                        mainCallback();
                    } else if (error) {
                        console.log(util.inspect("Tweet Error: " + error, false, null));
                        finalCallback();
                    } else {
                        finalCallback();
                    }
                });
            },
            function(mainCallback) {
                let savePackage = {};
                savePackage[task.storyID] = {status:"sent"};
                saveNewStory("hnkotlinbot/", savePackage, function() {
                    finalCallback();
                });
            },
            ]);
}, 1);

// Grab top 500 stories
function fetchTopStories() {
    var postedStories = {};
    serveLogActual();

    async.waterfall([
            function(outsideCallback) {
                grabDBSnapshot(function(snapshotOfDB) {
                    postedStories["hnkotlinbot"] = snapshotOfDB.hnkotlinbot;
                    outsideCallback();
                });
            },
            function(outsideCallback) {
                request({
                    url: "https://hacker-news.firebaseio.com/v0/topstories.json",
                    json: true
                }, function (error, response, groupOfStories) {
                    if (!error && response.statusCode === 200) {

                        console.log("before");
                        console.log(postedStories);

                        let arrayOfStoryIDs = Object.keys(postedStories.hnkotlinbot);
                        console.log(arrayOfStoryIDs)

                        let cleanStoriesList = groupOfStories.filter(function(val) {
                            let stringVal = val.toString();
                            return arrayOfStoryIDs.indexOf(stringVal) == -1;
                        });

                        for (i = 0; i < cleanStoriesList.length; i++) {
                            // fetch actual story to check it's title
                            q.push({ url: 'https://hacker-news.firebaseio.com/v0/item/' + cleanStoriesList[i] + '.json', storyID: cleanStoriesList[i]
                            });
                        }
                        outsideCallback();
                    } else {
                        console.log(util.inspect("Error on fetchTopStories: " + error, false, null));
                    }
                })
            },
            ]);
}

// Log time
function serveLogActual() {
    let currentDateActual = new Date(new Date().getTime() + -(new Date().getTimezoneOffset()/60) * 3600 * 1000);
    console.log("Running HN_Vimmy_Bot Scan: " + currentDateActual);
}

// start script
fetchTopStories();
<commit_msg>removes extra log statements<commit_after>// HN VImmy Bot
// Mike P Land
// Every Hour Scans Hacker News For Stories on Vim and Tweets Them, see mikepland.com/hn_vimmy_bot
// Script is being run with Crontab, ($ crontab -e)

let currentDateActual = new Date(new Date().getTime() + -(new Date().getTimezoneOffset()/60) * 3600 * 1000);
console.log("Running HN_Kotlin_Bot Scan: " + currentDateActual);

var request = require("request")
var Twitter = require("twitter")
var googl = require('goo.gl');
var async = require('async');
var util = require('util');
var admin = require("firebase-admin");

var chatEmoji = '💬';
var linkEmoji = '🔗';

// Set a developer key (_required by Google_; see http://goo.gl/4DvFk for more info.)
googl.setKey(process.env.hn_vimmy_bot_google_api_key);

// Get currently set developer key
googl.getKey();

var client = new Twitter({
    consumer_key: process.env.twitter_kotlin_consumer_key,
    consumer_secret: process.env.twitter_kotlin_consumer_secret,
    access_token_key: process.env.twitter_kotlin_access_token_key,
    access_token_secret: process.env.twitter_kotlin_access_token_secret
});

admin.initializeApp({
    credential: admin.credential.cert("/home/pi/newDayPi/HN_Vimmy_Bot/config/hnbot-8bb67-firebase-adminsdk-rszpo-c0cd32c24f.json"),
   // credential: admin.credential.cert("./config/hnbot-8bb67-firebase-adminsdk-rszpo-c0cd32c24f.json"),
    databaseURL: "https://hnbot-8bb67.firebaseio.com/"
});

var db = admin.database();
var ref = db.ref("/bots");

function grabDBSnapshot(callback) {
    ref.on("value", function(snapshot) {
        ref.off();
        callback(snapshot.val());
    }, function (errorObject) {
        console.log("The read failed: " + errorObject.code);
        process.exit(1);
    });
};

function saveNewStory(botPWD, savePackage, saveCallback) {
    console.log("Saving User Infomation To Database");
    ref.child(botPWD).update(savePackage).then(function() {
        console.log("Successfully Saved User Info to Database");
        saveCallback();
    }).catch(function(error) {
        console.log("Firebase Error: " + error);
        saveCallback();
    });
}

// Async makes sure to keep callback straight
var q = async.queue(function (task, finalCallback) {
    async.waterfall([
            function(mainCallback) {
                request(task.url, {timeout: 8000}, function(err, res, body) {
                    if (err) {
                        console.log(util.inspect("Error in fetchStory " + err, false, null));
                        finalCallback();
                    } else if (res.statusCode != 200) {
                        console.log(util.inspect("Error in fetchStory response not 200 " + res.statusCode, false, null));
                        finalCallback();
                    } else {
                        mainCallback(null, body)
                    }
                });
            },
            function(body, mainCallback) {
                var storyActualJSON = JSON.parse(body);

                if (storyActualJSON.title.match(/kotlin\b/gi)) {
                    // shorten HN Link
                    console.log("Found story on Kotlin: " + storyActualJSON.title);
                    console.log("Shortening HN Discussion Link");
                    googl.shorten('https://news.ycombinator.com/item?id=' + storyActualJSON.id)
                        .then(function (shortUrl) {
                            // Shorten Story Link
                            console.log("Link Successfully Shortened");
                            mainCallback(null, storyActualJSON, shortUrl);
                        })
                    .catch(function (err) {
                        console.log(util.inspect("Hacker News Link Error: " + err, false, null));
                        finalCallback();
                    });
                } else {
                    // console.log("no match for " + storyActualJSON.title)
                    finalCallback();
                }
            },
            function(storyActualJSON, hnLink, mainCallback) {
                console.log("Checking to see if story is \"ASK HN:\"");
                // check to see if post is "Ask HN:" and thus no story link
                if (storyActualJSON.url == undefined) {
                    var outgoingTweet = storyActualJSON.title + "\n" + chatEmoji + ": " + hnLink + "\n#HackerNews #Kotlin";
                    mainCallback(null, outgoingTweet);
                } else {
                    console.log("Shortening Story Link");
                    googl.shorten(storyActualJSON.url)
                        .then(function (shortUrl) {
                            console.log("Successfully Shortened Story Link");
                            var outgoingTweet = storyActualJSON.title + "\n" + chatEmoji + " " + hnLink + "\n" + linkEmoji + " " + shortUrl + "\n#HackerNews #Kotlin"; // add up to 132 max characters by my count, 80 max on HN
                            mainCallback(null, outgoingTweet)
                        })
                    .catch(function (err) {
                        console.log(util.inspect("Story Link Error: " + err, false, null));
                        finalCallback();
                    });
                }
            },
            function(outgoingTweet, mainCallback) {
                console.error("Tweeting out Story");
                client.post('statuses/update', {status: outgoingTweet},  function(error, tweet, response){
                    if (!error && response.statusCode === 200) {
                        console.log("Just Successfully Tweeted");
                        mainCallback();
                    } else if (error) {
                        console.log(util.inspect("Tweet Error: " + error, false, null));
                        finalCallback();
                    } else {
                        finalCallback();
                    }
                });
            },
            function(mainCallback) {
                let savePackage = {};
                savePackage[task.storyID] = {status:"sent"};
                saveNewStory("hnkotlinbot/", savePackage, function() {
                    finalCallback();
                });
            },
            ]);
}, 1);

q.drain = function() {
    console.log("----------------------------------- SCAN COMPLETE -----------------------------------");
    process.exit(1);
};

// Grab top 500 stories
function fetchTopStories() {
    var postedStories = {};
    async.waterfall([
            function(outsideCallback) {
                grabDBSnapshot(function(snapshotOfDB) {
                    postedStories["hnkotlinbot"] = snapshotOfDB.hnkotlinbot;
                    outsideCallback();
                });
            },
            function(outsideCallback) {
                request({
                    url: "https://hacker-news.firebaseio.com/v0/topstories.json",
                    json: true
                }, function (error, response, groupOfStories) {
                    if (!error && response.statusCode === 200) {
                        let arrayOfStoryIDs = Object.keys(postedStories.hnkotlinbot);

                        let cleanStoriesList = groupOfStories.filter(function(val) {
                            let stringVal = val.toString();
                            return arrayOfStoryIDs.indexOf(stringVal) == -1;
                        });

                        for (i = 0; i < cleanStoriesList.length; i++) {
                            // fetch actual story to check it's title
                            q.push({ url: 'https://hacker-news.firebaseio.com/v0/item/' + cleanStoriesList[i] + '.json', storyID: cleanStoriesList[i]
                            });
                        }
                        outsideCallback();
                    } else {
                        console.log(util.inspect("Error on fetchTopStories: " + error, false, null));
                    }
                })
            },
            ]);
}

// start script
fetchTopStories();
<|endoftext|>


<commit_before>var Messages = {};

var sdk = new Cocoafish('1PlafvOb0KsfJhWw68tWkGiVt3IkhjxR');

Messages.showInbox = function(){
	sdk.sendRequest('messages/show/inbox.json', 'GET', null, callback);
};

function callback(data) {
  if(data) {
    if(data.meta) {
      var meta = data.meta;
      if(meta.status == 'ok' && meta.code == 200 && meta.method_name == 'showMessagesInbox') {
        var messages = data.response.messages;
        Ti.API.log(messages);
      }
    }
  }
}<commit_msg>added send message functionality<commit_after>var Messages = {};

var sdk = new Cocoafish('1PlafvOb0KsfJhWw68tWkGiVt3IkhjxR');

Messages.showInbox = function(){
	sdk.sendRequest('messages/show/inbox.json', 'GET', null, function(){
	  if(data) {
        if(data.meta) {
          var meta = data.meta;
          if(meta.status == 'ok' && meta.code == 200 && meta.method_name == 'showMessagesInbox') {
            var messages = data.response.messages;
            Ti.API.log(messages);
          }
        }
      }
    });

};

Messages.create = function(_data){
  var sdk = new Cocoafish('1PlafvOb0KsfJhWw68tWkGiVt3IkhjxR');  // app key
  Users.getUsersFromClub(_data.club, function(users){
  	var userIds = function(users){
  		var returnString= '';
  		for(var i=0, iMax=users.length;i<iMax;i++){
  			returnString+=users[i].id;
  		}
  		return returnString;
  	}
  	var data = {
  	  subject : _data.subject,
  	  body : _data.body,
  	  to_ids: userIds
  	}
  	sdk.sendRequest('messages/create.json', 'POST', data, callback);
  });

};
<|endoftext|>


<commit_before>window.Export = function(templates, source, job) {
  var Job = Backbone.Model.extend({});
  Job.prototype.url = function() { return '/mbtiles.json?id='+ source.id; };

  var Upload = Backbone.Model.extend({});
  Upload.prototype.url = function() { return '/upload.json?id='+ source.id; };

  var Modal = new views.Modal({
    el: $('.modal-content'),
    templates: templates
  });

  var Exporter = Backbone.View.extend({});
  Exporter.prototype.events = {
    'click .js-cancel': 'cancel',
    'click .js-recache': 'recache',
    'click .js-upload': 'upload'
  };
  Exporter.prototype.poll = function() {
    var model = this.model;
    var view = this;
    model.fetch({
      success:function() {
        if (!model.get('progress')) {
          console.log(model.get('type'), model.get('progress'))
          view.refresh();
        } else {
          view.timeout = setTimeout(view.poll, 200);
        }
      },
      error:function() {}
    });
  };
  Exporter.prototype.initialize = function() {
    _(this).bindAll('poll', 'refresh');
    this.model.on('change', this.refresh);
    this.poll();
  };
  Exporter.prototype.refresh = function() {
    console.log(this.model.get('type'), this.model.get('progress'));
    if (!this.model.get('progress')) {
      console.log('no progress, resetting');
      var pct = '100.0';
      var spd = 0;
      this.$('.size').text(templates.exportsize(this.model.get('size')));
      $('body').removeClass('task').addClass('stat');
    } else {
      var pct = this.model.get('progress').percentage || 0;
      var spd = this.model.get('progress').delta || 0;
      $('body').removeClass('stat').addClass('task');
    }
    var pctel = this.$('.percent');
    var target = parseFloat(pct);
    var tweenpct = function() {
      var current = parseFloat(pctel.text());
      if (target === 0) return pctel.text('0.0');
      if (current >= target) return;
      pctel.text((current + 0.1).toFixed(1));
      setTimeout(tweenpct,50/(target-current)|0);
    };
    tweenpct();
    this.$('.progress .fill').css({width:pct+'%'});
    this.$('.speed').text(spd);
  };
  Exporter.prototype.recache = function() {
    var view = this;
    if (this.model.get('type') != 'export') {
      job.type = 'export';
      this.model = new Job(job);
    }

    _(this).bindAll('poll', 'refresh');
    this.model.on('change', this.refresh);

    this.model.save({}, {
      success: function() { view.poll(); }
    });
    return false;
  };
  Exporter.prototype.upload = function() {
    var view = this;
    job.type = 'upload';
    job.progress = null;
    this.model = new Upload(job);

    _(this).bindAll('poll', 'refresh');
    this.model.on('change', this.refresh);

    this.model.save({}, {
      success: function() { view.poll(); }
    });
    return false;
  };
  Exporter.prototype.cancel = function(ev) {
    var href = $(ev.currentTarget).attr('href');
    if (this.timeout) clearTimeout(this.timeout);
    this.model.destroy({
      success: function() { window.location.href = href }
    });
    return false;
  };

  var exporter = new Exporter({
    el: document.body,
    model: new Job(job)
  });
};
<commit_msg>update ui for various states of upload<commit_after>window.Export = function(templates, source, job) {
  var Job = Backbone.Model.extend({});
  Job.prototype.url = function() { return '/mbtiles.json?id='+ source.id; };

  var Upload = Backbone.Model.extend({});
  Upload.prototype.url = function() { return '/upload.json?id='+ source.id; };

  var Modal = new views.Modal({
    el: $('.modal-content'),
    templates: templates
  });

  var Exporter = Backbone.View.extend({});
  Exporter.prototype.events = {
    'click .js-cancel': 'cancel',
    'click .js-recache': 'recache',
    'click .js-upload': 'upload'
  };
  Exporter.prototype.poll = function() {
    var model = this.model;
    var view = this;
    model.fetch({
      success:function() {
        if (!model.get('progress')) {
          view.refresh();
        } else {
          view.timeout = setTimeout(view.poll, 200);
        }
      },
      error:function() {}
    });
  };
  Exporter.prototype.initialize = function() {
    _(this).bindAll('poll', 'refresh');
    this.model.on('change', this.refresh);
    this.poll();
  };
  Exporter.prototype.refresh = function() {
    if (source.mapid) {
      if (!this.model.get('update')) $('.js-upload').html('Already Uploaded').addClass('disabled').prop('title', source.mapid);
      else $('.js-upload').html('Upload Update').removeClass('disabled').prop('title', source.mapid);
    } else {
      $('.js-upload').html('Upload').prop('title', null);
    }
    if (!this.model.get('progress')) {
      var pct = '100.0';
      var spd = 0;
      this.$('.size').text(templates.exportsize(this.model.get('size')));
      $('body').removeClass('task').addClass('stat');
    } else {
      var pct = this.model.get('progress').percentage || 0;
      var spd = this.model.get('progress').delta || 0;
      $('.js-cancel').html('Cancel ' + this.model.get('type'));
      if (this.model.get('type') === 'export') this.model.set({update: true});
      $('body').removeClass('stat').addClass('task');
    }
    var pctel = this.$('.percent');
    var target = parseFloat(pct);
    var tweenpct = function() {
      var current = parseFloat(pctel.text());
      if (target === 0) return pctel.text('0.0');
      if (current >= target) return;
      pctel.text((current + 0.1).toFixed(1));
      setTimeout(tweenpct,50/(target-current)|0);
    };
    tweenpct();
    this.$('.progress .fill').css({width:pct+'%'});
    this.$('.speed').text(spd);
  };
  Exporter.prototype.recache = function() {
    var view = this;
    if (this.model.get('type') != 'export') {
      job.type = 'export';
      this.model = new Job(job);
    }

    _(this).bindAll('poll', 'refresh');
    this.model.on('change', this.refresh);

    this.model.save({}, {
      success: function() { view.poll(); }
    });
    return false;
  };
  Exporter.prototype.upload = function() {
    var view = this;
    job.type = 'upload';
    job.progress = null;
    this.model = new Upload(job);

    _(this).bindAll('poll', 'refresh');
    this.model.on('change', this.refresh);

    this.model.save({}, {
      success: function() { view.poll(); }
    });
    return false;
  };
  Exporter.prototype.cancel = function(ev) {
    var href = $(ev.currentTarget).attr('href');
    if (this.timeout) clearTimeout(this.timeout);
    this.model.destroy({
      success: function() { window.location.href = href; }
    });
    return false;
  };

  var exporter = new Exporter({
    el: document.body,
    model: new Job(job)
  });
};
<|endoftext|>


<commit_before>var _ = require('underscore');

module.exports = {
	// Normalize the different ways of specifying criteria into a uniform object
	criteria: function normalizeCriteria (criteria) {
		if(!criteria) return {
			where: {}
		};

		// Empty undefined values from criteria object
		_.each(criteria, function(val, key) {
			if(_.isUndefined(val)) delete criteria[key];
		});

		// Convert id and id strings into a criteria
		if((_.isFinite(criteria) || (_.isString(criteria)) && +criteria > 0)) {
			criteria = {
				id: +criteria
			};
		}

		// Return string to indicate an error
		if(!_.isObject(criteria)) return('Invalid options/criteria :: ' + criteria);

		// If criteria doesn't seem to contain operational keys, assume all the keys are criteria
		if(!criteria.where && !criteria.limit && !criteria.skip && !criteria.sort) {

			// Delete any residuals and then use the remaining keys as attributes in a criteria query
			delete criteria.where;
			delete criteria.limit;
			delete criteria.skip;
			delete criteria.skip;
			criteria = {
				where: criteria
			};
		}
		// If where is null, turn it into an object
		else if(_.isNull(criteria.where)) criteria.where = {};

		// If any item in criteria is a parsable finite number, use that
		for(var attrName in criteria.where) {
			if(Math.pow(+criteria.where[attrName], 2) > 0) {
				criteria.where[attrName] = +criteria.where[attrName];
			}
		}

		// Normalize sort criteria
		if(criteria.sort) {
			// Split string into attr and sortDirection parts (default to 'asc')
			if(_.isString(criteria.sort)) {
				var parts = _.str.words(criteria.sort);
				parts[1] = parts[1] ? parts[1].toLowerCase() : 'asc';
				if(parts.length !== 2 || (parts[1] !== 'asc' && parts[1] !== 'desc')) {
					throw new Error('Invalid sort criteria :: ' + criteria.sort);
				}
				criteria.sort = {};
				criteria.sort[parts[0]] = (parts[1] === 'asc') ? 1 : -1;
			}

			// Verify that user either specified a proper object
			// or provided explicit comparator function
			if(!_.isObject(criteria.sort) && !_.isFunction(criteria.sort)) {
				throw new Error('Invalid sort criteria for ' + attrName + ' :: ' + direction);
			}
		}

		return criteria;
	},

	/**
	 * Run a method on an object -OR- each item in an array and return the result
	 * Also handle errors gracefully
	 */
	pluralize: function pluralize (collection, application) {
		if(_.isArray(collection)) {
			return _.map(collection, application);
		} else if(_.isObject(collection)) {
			return application(collection);
		} else {
			throw "Invalid collection passed to plural aggreagator:" + collection;
		}
	}
};<commit_msg>Now where: {} is marshalled to where: null.<commit_after>var _ = require('underscore');

module.exports = {
	// Normalize the different ways of specifying criteria into a uniform object
	criteria: function normalizeCriteria (criteria) {
		if(!criteria) return {
			where: null
		};

		// Empty undefined values from criteria object
		_.each(criteria, function(val, key) {
			if(_.isUndefined(val)) delete criteria[key];
		});

		// Convert id and id strings into a criteria
		if((_.isFinite(criteria) || (_.isString(criteria)) && +criteria > 0)) {
			criteria = {
				id: +criteria
			};
		}

		// Return string to indicate an error
		if(!_.isObject(criteria)) return('Invalid options/criteria :: ' + criteria);

		// If criteria doesn't seem to contain operational keys, assume all the keys are criteria
		if(!criteria.where && !criteria.limit && !criteria.skip && !criteria.sort) {

			// Delete any residuals and then use the remaining keys as attributes in a criteria query
			delete criteria.where;
			delete criteria.limit;
			delete criteria.skip;
			delete criteria.skip;
			criteria = {
				where: criteria
			};
		}
		// If where is null, turn it into an object
		else if(_.isNull(criteria.where)) criteria.where = {};

		// If any item in criteria is a parsable finite number, use that
		for(var attrName in criteria.where) {
			if(Math.pow(+criteria.where[attrName], 2) > 0) {
				criteria.where[attrName] = +criteria.where[attrName];
			}
		}

		// If WHERE is {}, always change it back to null
		if (criteria.where && _.keys(criteria.where).length === 0) {
			criteria.where = null;
		}

		// Normalize sort criteria
		if(criteria.sort) {
			// Split string into attr and sortDirection parts (default to 'asc')
			if(_.isString(criteria.sort)) {
				var parts = _.str.words(criteria.sort);
				parts[1] = parts[1] ? parts[1].toLowerCase() : 'asc';
				if(parts.length !== 2 || (parts[1] !== 'asc' && parts[1] !== 'desc')) {
					throw new Error('Invalid sort criteria :: ' + criteria.sort);
				}
				criteria.sort = {};
				criteria.sort[parts[0]] = (parts[1] === 'asc') ? 1 : -1;
			}

			// Verify that user either specified a proper object
			// or provided explicit comparator function
			if(!_.isObject(criteria.sort) && !_.isFunction(criteria.sort)) {
				throw new Error('Invalid sort criteria for ' + attrName + ' :: ' + direction);
			}
		}

		return criteria;
	},

	/**
	 * Run a method on an object -OR- each item in an array and return the result
	 * Also handle errors gracefully
	 */
	pluralize: function pluralize (collection, application) {
		if(_.isArray(collection)) {
			return _.map(collection, application);
		} else if(_.isObject(collection)) {
			return application(collection);
		} else {
			throw "Invalid collection passed to plural aggreagator:" + collection;
		}
	}
};<|endoftext|>


<commit_before>(function ($) {
    if ('undefined' != typeof window.toastr) {
        window.toastr.options = {
            'progressBar': true,
            'closeButton': true
        };
    }
    $(function () {
        window.CmfcmfMediaModule = window.CmfcmfMediaModule || {};
        window.CmfcmfMediaModule.Util = {
            alert: function (title, body) {
                alert(title + "\n" + body);
            },
            Ajax: {
                fail: function (data) {
                    var errorText = "Sorry, the AJAX request could not be finished. Please try again.";
                    if (data.responseJSON && data.responseJSON.error) {
                        errorText = data.responseJSON.error;
                    } else if (data.status == 403) {
                        errorText = "You do not have permission to execute this action."
                    }
                    if ('undefined' != typeof window.toastr) {
                        window.toastr["error"](errorText, 'Something went wrong!');
                    } else {
                        alert('Something went wrong!');
                    }
                },
                makeExternalRequest: function (url, done, fail, always) {
                    var xmlhttp;

                    if (window.XMLHttpRequest) {
                        // code for IE7+, Firefox, Chrome, Opera, Safari
                        xmlhttp = new XMLHttpRequest();
                    } else {
                        // code for IE6, IE5
                        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                    }

                    xmlhttp.onreadystatechange = function() {
                        if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
                            if(xmlhttp.status == 200){
                                done(xmlhttp.responseText);
                            } else {
                                fail();
                            }
                            if (typeof always == "function") {
                                always();
                            }
                        }
                    };

                    xmlhttp.open("GET", url, true);
                    xmlhttp.send();
                }
            },
            // Taken from http://stackoverflow.com/a/1219983/2560557
            htmlEncode: function(value) {
                //create a in-memory div, set it's inner text(which jQuery automatically encodes)
                //then grab the encoded contents back out.  The div never exists on the page.
                return $('
').text(value).html();
            },
            htmlAttrEncode: function(value) {
                var map = {
                    '&': '&',
                    '<': '<',
                    '>': '>',
                    '"': '"',
                    "'": '''
                };

                return String(value).replace(/[&<>"']/g, function(m) { return map[m]; });
            },
            htmlDecode: function(value){
                return $('
').html(value).text();
            },
            nl2br: function (str) {
                //  discuss at: http://phpjs.org/functions/nl2br/
                // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
                // improved by: Philip Peterson
                // improved by: Onno Marsman
                // improved by: Atli Þór
                // improved by: Brett Zamir (http://brett-zamir.me)
                // improved by: Maximusya
                // bugfixed by: Onno Marsman
                // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
                //    input by: Brett Zamir (http://brett-zamir.me)

                return (str + '')
                    .replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2');
            },
            lcfirst: function (str) {
                //  discuss at: http://phpjs.org/functions/lcfirst/
                // original by: Brett Zamir (http://brett-zamir.me)
                //   example 1: lcfirst('Kevin Van Zonneveld');
                //   returns 1: 'kevin Van Zonneveld'

                str += '';
                var f = str.charAt(0)
                    .toLowerCase();
                return f + str.substr(1);
            },
            liveUpdateDropdownButton: function($element) {
                $element.parent().find("> .dropdown-menu li a").click(function(){
                    $element
                        .html($(this).text() + ' ')
                        .val($(this).data('value'))
                        .change();
                });
            }
        };
    });
})(jQuery);
<commit_msg>show error details<commit_after>(function ($) {
    if ('undefined' != typeof window.toastr) {
        window.toastr.options = {
            'progressBar': true,
            'closeButton': true
        };
    }
    $(function () {
        window.CmfcmfMediaModule = window.CmfcmfMediaModule || {};
        window.CmfcmfMediaModule.Util = {
            alert: function (title, body) {
                alert(title + "\n" + body);
            },
            Ajax: {
                fail: function (data) {
                    var errorText = 'Sorry, the AJAX request could not be finished. Please try again.';
                    if (data.responseJSON && data.responseJSON.error) {
                        errorText = data.responseJSON.error;
                    } else if (data.status == 403) {
                        errorText = 'You do not have permission to execute this action.'
                    }
                    if ('undefined' != typeof window.toastr) {
                        window.toastr['error'](errorText, 'Something went wrong!');
                    } else {
                        alert('Something went wrong!' + ' ' + errorText);
                    }
                },
                makeExternalRequest: function (url, done, fail, always) {
                    var xmlhttp;

                    if (window.XMLHttpRequest) {
                        // code for IE7+, Firefox, Chrome, Opera, Safari
                        xmlhttp = new XMLHttpRequest();
                    } else {
                        // code for IE6, IE5
                        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                    }

                    xmlhttp.onreadystatechange = function() {
                        if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
                            if(xmlhttp.status == 200){
                                done(xmlhttp.responseText);
                            } else {
                                fail();
                            }
                            if (typeof always == "function") {
                                always();
                            }
                        }
                    };

                    xmlhttp.open("GET", url, true);
                    xmlhttp.send();
                }
            },
            // Taken from http://stackoverflow.com/a/1219983/2560557
            htmlEncode: function(value) {
                //create a in-memory div, set it's inner text(which jQuery automatically encodes)
                //then grab the encoded contents back out.  The div never exists on the page.
                return $('
').text(value).html();
            },
            htmlAttrEncode: function(value) {
                var map = {
                    '&': '&',
                    '<': '<',
                    '>': '>',
                    '"': '"',
                    "'": '''
                };

                return String(value).replace(/[&<>"']/g, function(m) { return map[m]; });
            },
            htmlDecode: function(value){
                return $('
').html(value).text();
            },
            nl2br: function (str) {
                //  discuss at: http://phpjs.org/functions/nl2br/
                // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
                // improved by: Philip Peterson
                // improved by: Onno Marsman
                // improved by: Atli Þór
                // improved by: Brett Zamir (http://brett-zamir.me)
                // improved by: Maximusya
                // bugfixed by: Onno Marsman
                // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
                //    input by: Brett Zamir (http://brett-zamir.me)

                return (str + '')
                    .replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2');
            },
            lcfirst: function (str) {
                //  discuss at: http://phpjs.org/functions/lcfirst/
                // original by: Brett Zamir (http://brett-zamir.me)
                //   example 1: lcfirst('Kevin Van Zonneveld');
                //   returns 1: 'kevin Van Zonneveld'

                str += '';
                var f = str.charAt(0)
                    .toLowerCase();
                return f + str.substr(1);
            },
            liveUpdateDropdownButton: function($element) {
                $element.parent().find("> .dropdown-menu li a").click(function(){
                    $element
                        .html($(this).text() + ' ')
                        .val($(this).data('value'))
                        .change();
                });
            }
        };
    });
})(jQuery);
<|endoftext|>


<commit_before>Ext.define('TvShows.model.Show', {
    extend: 'Ext.data.Model',

    fields: [
        { name: 'first_aired', type: 'date' },
        { name: 'title', type: 'string' },
        { name: 'episode', type: 'auto' },
        { name: 'genre', type: 'auto' },
        { name: 'overview', type: 'string' },
        { name: 'network', type: 'string' },
        { name: 'runtime', type: 'int' },
        { name: 'logo', type: 'string' },
        { name: 'thumb', type: 'string' },
        { name: 'fanart', type: 'string' },
        { name: 'year', type: 'int' },
        { name: 'slug', type: 'string' }

    ]
});
<commit_msg>Mapp Show model fields to feed<commit_after>Ext.define('TvShows.model.Show', {
    extend: 'Ext.data.Model',

    requires: [
        'Ext.data.field.Date',
    ],

    fields: [
        {
            type: 'date',
            name: 'first_aired',
            dateFormat: 'C',
            convert: function(data) {
                return data;
            },
            mapping: 'show.first_aired'
        },
        { name: 'title', type: 'string', mapping: 'show.title' },
        { name: 'episode', type: 'auto', mapping: 'show.year' },
        { name: 'genre', type: 'auto', mapping: 'show.genre' },
        { name: 'overview', type: 'string', mapping: 'show.overview' },
        { name: 'network', type: 'string', mapping: 'show.network' },
        { name: 'runtime', type: 'int', mapping: 'show.runtime' },
        { name: 'logo', type: 'string', mapping: 'show.images.logo.full' },
        { name: 'thumb', type: 'string', mapping: 'show.images.poster.thumb' },
        { name: 'fanart', type: 'string', mapping: 'show.images.fanart.full' },
        { name: 'year', type: 'int', mapping: 'show.year' },
        { name: 'slug', type: 'string', mapping: 'show.ids.slug' }

    ]
});
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 */

// ==UserScript==
// @id             d986d257-05de-4625-a8ca-d2a8791a1a60
// @name           Note
// @include        about:blank#d986d257-05de-4625-a8ca-d2a8791a1a60#*
// @run-at         document-end
// @version        1.0
// ==/UserScript==

(function(){

    // underscore framework
    function _(selector) {

        var elements = [];

        // getElementById
        var match = selector.match('^#(.+)$');
        if (match != null){
            elements.push(document.getElementById(match[1]));
        }

        // getElementsByTagName
        var match = selector.match('^([a-z]+)$');
        if (match != null){
            var items = document.getElementsByTagName(match[1]);
            for (var i = 0; i < items.length; i++){
                elements.push(items[i]);
            }
        }

        // getElementsByClassName
        var match = selector.match('^\.(.+)$');
        if (match != null){
            var items = document.getElementsByClassName(match[1]);
            for (var i = 0; i < items.length; i++){
                elements.push(items[i]);
            }
        }

        // add additional function to resulting array

        elements['html'] = function(text) {

            if (text == undefined){
                return elements[0].innerHTML;
            }

            for (var i = 0; i < elements.length; i++) {
                elements[i].innerHTML = text;
            }
        };

        elements['each'] = function(callback) {
            for (var i = 0; i < elements.length; i++) {
                callback.call(elements[i]);
            }
        };

        elements['html'] = function(text) {

            if (text == undefined){
                return elements[0].innerHTML;
            }

            for (var i = 0; i < elements.length; i++) {
                elements[i].innerHTML = text;
            }
        };

        elements['value'] = function(text) {

            if (text == undefined){
                return elements[0].value;
            }
        };

        elements['click'] = function(callback) {
            for (var i = 0; i < elements.length; i++) {
                elements[i].addEventListener('click', callback);
            }
        };

        elements['css'] = function(name, value) {
            for (var i = 0; i < elements.length; i++) {
                elements[i].style.setProperty(name, value);
            }
        };

        return elements;
    };

    // append style to document
    this.addStyle = function(content) {
        var oHead = document.getElementsByTagName('head')[0];
        var oStyle = document.createElement('style');
        oStyle.type = 'text/css';
        oStyle.textContent = content;
        oHead.appendChild(oStyle);
    };

    // set html content of <body> .. </body>
    this.setHTML = function(content) {
        document.body.innerHTML = content;
    };

    this.addStyle(include('style.css'));
    this.setHTML(include('index.html'));

    _('#commandShowText').click(function() {
        _('article').css('display','none');
        _('#article-text').css('display','block');
    });

    _('#commandShowHTML').click(function() {
        _('article').css('display','none');
        _('#article-html').css('display','block');
    });

    _('#commandShowView').click(function() {
        _('article').css('display','none');
        _('#article-view').css('display','block');
    });

    _('#commandShowHelp').click(function() {
        _('article').css('display','none');
        _('#article-help').css('display','block');
    });

    var Note = {
         'elementId': '#text-content'
        ,'prefixLength': 38
        ,'textOriginal': null
        ,'open': function() {
            this.textOriginal = _(this.elementId).html();
            _(this.elementId).html(unescape(
                location.hash.substring(this.prefixLength)
                ));
            _(this.elementId).each(function(){
                this.addEventListener('keyup', function() {
                    Note.set();
                });
            });
        }
        ,'set': function() {
            location.hash = location.hash.substring(0,this.prefixLength)
                + _(this.elementId).value()
                ;
        }
        ,'get': function() {
            return _(this.elementId).value();
        }
    };

    Note.open();

})();
<commit_msg>[bugfix] textOriginal should extracted from location.hash<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 */

// ==UserScript==
// @id             d986d257-05de-4625-a8ca-d2a8791a1a60
// @name           Note
// @include        about:blank#d986d257-05de-4625-a8ca-d2a8791a1a60#*
// @run-at         document-end
// @version        1.0
// ==/UserScript==

(function(){

    // underscore framework
    function _(selector) {

        var elements = [];

        // getElementById
        var match = selector.match('^#(.+)$');
        if (match != null){
            elements.push(document.getElementById(match[1]));
        }

        // getElementsByTagName
        var match = selector.match('^([a-z]+)$');
        if (match != null){
            var items = document.getElementsByTagName(match[1]);
            for (var i = 0; i < items.length; i++){
                elements.push(items[i]);
            }
        }

        // getElementsByClassName
        var match = selector.match('^\.(.+)$');
        if (match != null){
            var items = document.getElementsByClassName(match[1]);
            for (var i = 0; i < items.length; i++){
                elements.push(items[i]);
            }
        }

        // add additional function to resulting array

        elements['html'] = function(text) {

            if (text == undefined){
                return elements[0].innerHTML;
            }

            for (var i = 0; i < elements.length; i++) {
                elements[i].innerHTML = text;
            }
        };

        elements['each'] = function(callback) {
            for (var i = 0; i < elements.length; i++) {
                callback.call(elements[i]);
            }
        };

        elements['html'] = function(text) {

            if (text == undefined){
                return elements[0].innerHTML;
            }

            for (var i = 0; i < elements.length; i++) {
                elements[i].innerHTML = text;
            }
        };

        elements['value'] = function(text) {

            if (text == undefined){
                return elements[0].value;
            }
        };

        elements['click'] = function(callback) {
            for (var i = 0; i < elements.length; i++) {
                elements[i].addEventListener('click', callback);
            }
        };

        elements['css'] = function(name, value) {
            for (var i = 0; i < elements.length; i++) {
                elements[i].style.setProperty(name, value);
            }
        };

        return elements;
    };

    // append style to document
    this.addStyle = function(content) {
        var oHead = document.getElementsByTagName('head')[0];
        var oStyle = document.createElement('style');
        oStyle.type = 'text/css';
        oStyle.textContent = content;
        oHead.appendChild(oStyle);
    };

    // set html content of <body> .. </body>
    this.setHTML = function(content) {
        document.body.innerHTML = content;
    };

    this.addStyle(include('style.css'));
    this.setHTML(include('index.html'));

    _('#commandShowText').click(function() {
        _('article').css('display','none');
        _('#article-text').css('display','block');
    });

    _('#commandShowHTML').click(function() {
        _('article').css('display','none');
        _('#article-html').css('display','block');
    });

    _('#commandShowView').click(function() {
        _('article').css('display','none');
        _('#article-view').css('display','block');
    });

    _('#commandShowHelp').click(function() {
        _('article').css('display','none');
        _('#article-help').css('display','block');
    });

    var Note = {
         'elementId': '#text-content'
        ,'prefixLength': 38
        ,'textOriginal': null
        ,'open': function() {

            var textOriginal = unescape(
                location.hash.substring(this.prefixLength)
                );

            _(this.elementId).html(textOriginal);
            this.textOriginal = textOriginal;
            _(this.elementId)[0].addEventListener('keyup', function() {
                Note.set();
            });
        }
        ,'set': function() {
            location.hash = location.hash.substring(0,this.prefixLength)
                + _(this.elementId).value()
                ;
        }
        ,'get': function() {
            return _(this.elementId).value();
        }
    };

    Note.open();

})();
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');

var dir = path.resolve(__dirname, '..');

module.exports = function(win) {
  win.once('page-title-updated', function() {
    var wc = win.webContents;
    wc.insertCSS(fs.readFileSync(dir + '/web/custom.css', 'utf8'));
    wc.executeJavaScript('module.paths.push("' + dir + '/node_modules");');
    wc.executeJavaScript('module.paths.push("' + dir + '/web");');
    wc.executeJavaScript('require("inject");');
  });
};
<commit_msg>re-inject upon reload<commit_after>var fs = require('fs');
var path = require('path');
var URL = require('url');

var dir = path.resolve(__dirname, '..');

module.exports = function(win) {
  var wc = win.webContents;
  wc.on('did-navigate', function(ev, url) {
    var host = URL.parse(url).host;
    if (host == 'inbox.google.com') {
      wc.insertCSS(fs.readFileSync(dir + '/web/custom.css', 'utf8'));
      wc.executeJavaScript('module.paths.push("' + dir + '/node_modules");');
      wc.executeJavaScript('module.paths.push("' + dir + '/web");');
      wc.executeJavaScript('require("inject");');
    }
  });
};
<|endoftext|>


<commit_before>function main() {
    var DISPLAY_WIDTH = 320;
    var DISPLAY_HEIGHT = 450;
    var STAGE_WIDTH = DISPLAY_WIDTH;
    var STAGE_HEIGHT = DISPLAY_WIDTH;
    var SCORE_LEFT = 16;
    var SCORE_TOP = 16;
    var SCORE_TITLE_WIDTH = 48;

    enchant();
    var core = new Core(DISPLAY_WIDTH, DISPLAY_HEIGHT);
    core.preload("img/chara1.png", "img/icon1.png", "img/cursor.png", "img/heart.png");
    core.fps = 15;
    core.onload = function () {
        var background = (function () {
            var sprite = new Sprite(STAGE_WIDTH, STAGE_HEIGHT);
            sprite.image = (function () {
                var surface = new Surface(STAGE_WIDTH, STAGE_HEIGHT);
                var context = surface.context;
                context.fillStyle = (function () {
                    var grad = context.createLinearGradient(0, 0, 0, STAGE_HEIGHT);
                    grad.addColorStop(0, "#cceedd");
                    grad.addColorStop(0.5, "#aaccbb");
                    grad.addColorStop(1, "#668877");
                    return grad;
                })();
                context.fillRect(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
                return surface;
            })();
            return sprite;
        })();
        var bear = (function () {
            var width = 32;
            var height = 32;
            var sprite = new Sprite(width, height);
            sprite.image = core.assets["img/chara1.png"];
            sprite.frame = [0];
            sprite.x = (STAGE_WIDTH / 2) - (width / 2);
            sprite.y = (STAGE_HEIGHT / 2) - (height / 2);
            return sprite;
        })();
        var controller = (function () {
            var areaWidth = STAGE_WIDTH;
            var areaHeight = DISPLAY_HEIGHT - STAGE_HEIGHT;
            var sprite = new Sprite(areaWidth, areaHeight);
            sprite.image = (function () {
                var surface = new Surface(areaWidth, areaHeight);
                surface.context.fillStyle = "#ffffff";
                surface.context.fillRect(0, 0, areaWidth, areaHeight);
                return surface;
            })();
            sprite.x = 0;
            sprite.y = STAGE_HEIGHT;
            return sprite;
        })();
        var cursor = (function () {
            var width = 120;
            var height = 120;
            var areaWidth = STAGE_WIDTH;
            var areaHeight = DISPLAY_HEIGHT - STAGE_HEIGHT;
            var sprite = new Sprite(width, height);
            sprite.image = core.assets["img/cursor.png"];
            sprite.x = (areaWidth / 2) - (width / 2);
            sprite.y = STAGE_HEIGHT + (areaHeight - height) / 2;
            return sprite;
        })();
        var scoreTitle = (function () {
            var label = new Label();
            label.text = "Score:";
            label.font = "14px/16px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif";
            label.x = SCORE_LEFT;
            label.y = SCORE_TOP;
            return label;
        })();
        var scoreNumber = (function () {
            var label = new Label();
            label.text = "0";
            label.font = "bold 16px/16px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif";
            label.x = SCORE_LEFT + SCORE_TITLE_WIDTH;
            label.y = SCORE_TOP;
            return label;
        })();

        var gameScene = new Scene();
        gameScene.addChild(background);
        gameScene.addChild(bear);
        gameScene.addChild(controller);
        gameScene.addChild(cursor);
        gameScene.addChild(scoreTitle);
        gameScene.addChild(scoreNumber);

        // 左右どちらのボタンが押されているかを管理します
        var INPUT_NONE = 0;
        var INPUT_LEFT = 1;
        var INPUT_RIGHT = 2;
        var currentInput = INPUT_NONE;

        // ハートをキャッチするたびに増える得点です
        var score = 0;

        // ボールがプレイヤーに当たった時に true になります
        var gameover = false;

        /**
         * ボタン上をタッチまたはスワイプした際に発火する関数です。
         * 以下の処理を行います。
         *
         * - ボタンのスプライトを変更し、押された感じを表現します
         * - プレイヤーのモーションを走っている状態にします
         *
         * @param {Event} e
         */
        var inputCursor = function (e) {
            var input = (e.x < STAGE_WIDTH / 2) ? INPUT_LEFT : INPUT_RIGHT;
            if (currentInput !== input) {
                currentInput = input;
                cursor.frame = [input];

                if (!gameover) {
                    var newScale = (currentInput === INPUT_RIGHT) ? 1 : -1;
                    bear.scaleX = newScale;
                    bear.frame = [0, 0, 1, 1, 0, 0, 2, 2];
                }
            }
        };

        /**
         * ボタンから指を離した際に発火する関数です。
         * 以下の処理を行います。
         *
         * - ボタンのスプライトをデフォルトに変更します
         * - プレイヤーのモーションを止まっている状態にします
         *
         * @param {Event} e
         */
        var stopCursor = function (e) {
            currentInput = INPUT_NONE;
            cursor.frame = [INPUT_NONE];
            if (!gameover) {
                bear.frame = [0];
            }
        };
        cursor.addEventListener(Event.TOUCH_START, inputCursor);
        cursor.addEventListener(Event.TOUCH_MOVE, inputCursor);
        cursor.addEventListener(Event.TOUCH_END, stopCursor);

        /**
         * フレーム毎に実行される関数です。
         * もしも右か左のボタンが押されていたら、プレイヤーの位置を移動させます。
         *
         * @param {Event} e
         */
        var moveBear = function (e) {
            if (currentInput === INPUT_NONE) {
                return;
            }

            var dx = (currentInput === INPUT_LEFT) ? -5 : 5;
            var newX = Math.min(Math.max(bear.x + dx, 0), STAGE_WIDTH - 32);
            bear.x = newX;
        };
        bear.addEventListener(Event.ENTER_FRAME, moveBear);

        var createHeart = function () {
            var width = 32;
            var height = 32;
            var sprite = new Sprite(width, height);
            sprite.image = core.assets["img/heart.png"];
            sprite.x = Math.random() * (STAGE_WIDTH - width);
            var topToBottom = (Math.random() < 0.5); // true: 上から下, false: 下から上
            sprite.y = topToBottom ? -width : STAGE_HEIGHT;
            sprite.frame = [0, 0, 0, 1, 1, 1];
            sprite.addEventListener(Event.ENTER_FRAME, function (e) {
                if (gameover) {
                    return;
                }
                sprite.y += topToBottom ? 3 : -3;
                var out = (topToBottom && STAGE_HEIGHT < sprite.y) || (!topToBottom && sprite.y < -width);
                if (out) {
                    gameScene.removeChild(sprite);
                }
                // プレイヤーがハートをキャッチしたら得点を +1 します
                if (sprite.within(bear, width / 2)) {
                    gameScene.removeChild(sprite);
                    score++;
                    scoreNumber.text = score;
                }
            });
            return sprite;
        };
        var createBall = function (e) {
            var width = 16;
            var height = 16;
            var sprite = new Sprite(width, height);
            sprite.image = core.assets["img/icon1.png"];
            sprite.x = Math.random() * (STAGE_WIDTH - width);
            var topToBottom = (Math.random() < 0.5); // true: 上から下, false: 下から上
            var speed = 2 + (Math.random() * 3);
            sprite.y = topToBottom ? - width : STAGE_HEIGHT;
            var frameIndex = (Math.random() < 0.5) ? 0 : 1;
            sprite.frame = [frameIndex];
            sprite.addEventListener(Event.ENTER_FRAME, function (e) {
                sprite.rotate(15);
                if (gameover) {
                    return;
                }
                sprite.y += topToBottom ? speed : - speed;
                var out = (topToBottom && STAGE_HEIGHT < sprite.y) || (!topToBottom && sprite.y < - width);
                if (out) {
                    gameScene.removeChild(sprite);
                }
                // ボールがプレイヤーに当たったらゲームオーバーとします
                if (sprite.within(bear, width)) {
                    gameover = true;
                    bear.frame = [3];
                    bear.removeEventListener(Event.ENTER_FRAME, moveBear);
                    bear.tl.moveTo(bear.x, STAGE_HEIGHT + 64, 15, function (t, b, c, d) {
                        var peak = 0.25;
                        var x = (t / d) - peak;
                        return 2 * (x * x * (c - b) + b - (peak * peak));
                    });
                    gameScene.removeEventListener(Event.ENTER_FRAME, createObject);
                }
            });
            return sprite;
        };
        var createObject = function (e) {
            var rand = Math.random();
            if (0.06 < rand) {
                return;
            }

            if (0.03 < rand) {
                var heart = createHeart();
                gameScene.insertBefore(heart, controller);
            } else {
                var ball = createBall();
                gameScene.insertBefore(ball, controller);
            }
        };
        gameScene.addEventListener(Event.ENTER_FRAME, createObject);
        core.replaceScene(gameScene);
    };
    core.start();
}
<commit_msg>Refactor: Add startNewGame()<commit_after>function main() {
    var DISPLAY_WIDTH = 320;
    var DISPLAY_HEIGHT = 450;
    var STAGE_WIDTH = DISPLAY_WIDTH;
    var STAGE_HEIGHT = DISPLAY_WIDTH;
    var SCORE_LEFT = 16;
    var SCORE_TOP = 16;
    var SCORE_TITLE_WIDTH = 48;

    // 左右どちらのボタンが押されているかを管理します
    var INPUT_NONE = 0;
    var INPUT_LEFT = 1;
    var INPUT_RIGHT = 2;

    enchant();
    var core = new Core(DISPLAY_WIDTH, DISPLAY_HEIGHT);
    core.preload("img/chara1.png", "img/icon1.png", "img/cursor.png", "img/heart.png");
    core.fps = 15;
    core.onload = function () {
        var newBackground = function () {
            var sprite = new Sprite(STAGE_WIDTH, STAGE_HEIGHT);
            sprite.image = (function () {
                var surface = new Surface(STAGE_WIDTH, STAGE_HEIGHT);
                var context = surface.context;
                context.fillStyle = (function () {
                    var grad = context.createLinearGradient(0, 0, 0, STAGE_HEIGHT);
                    grad.addColorStop(0, "#cceedd");
                    grad.addColorStop(0.5, "#aaccbb");
                    grad.addColorStop(1, "#668877");
                    return grad;
                })();
                context.fillRect(0, 0, STAGE_WIDTH, STAGE_HEIGHT);
                return surface;
            })();
            return sprite;
        };
        var newPlayer = function () {
            var width = 32;
            var height = 32;
            var sprite = new Sprite(width, height);
            sprite.image = core.assets["img/chara1.png"];
            sprite.frame = [0];
            sprite.x = (STAGE_WIDTH / 2) - (width / 2);
            sprite.y = (STAGE_HEIGHT / 2) - (height / 2);
            return sprite;
        };
        var newController = function () {
            var areaWidth = STAGE_WIDTH;
            var areaHeight = DISPLAY_HEIGHT - STAGE_HEIGHT;
            var sprite = new Sprite(areaWidth, areaHeight);
            sprite.image = (function () {
                var surface = new Surface(areaWidth, areaHeight);
                surface.context.fillStyle = "#ffffff";
                surface.context.fillRect(0, 0, areaWidth, areaHeight);
                return surface;
            })();
            sprite.x = 0;
            sprite.y = STAGE_HEIGHT;
            return sprite;
        };
        var newCursor = function () {
            var width = 120;
            var height = 120;
            var areaWidth = STAGE_WIDTH;
            var areaHeight = DISPLAY_HEIGHT - STAGE_HEIGHT;
            var sprite = new Sprite(width, height);
            sprite.image = core.assets["img/cursor.png"];
            sprite.x = (areaWidth / 2) - (width / 2);
            sprite.y = STAGE_HEIGHT + (areaHeight - height) / 2;
            return sprite;
        };
        var newScoreTitle = function () {
            var label = new Label();
            label.text = "Score:";
            label.font = "14px/16px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif";
            label.x = SCORE_LEFT;
            label.y = SCORE_TOP;
            return label;
        };
        var newScoreNumber = function () {
            var label = new Label();
            label.text = "0";
            label.font = "bold 16px/16px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif";
            label.x = SCORE_LEFT + SCORE_TITLE_WIDTH;
            label.y = SCORE_TOP;
            return label;
        };

        var startNewGame = function () {
            var gameScene = new Scene();
            var background = newBackground();
            var bear = newPlayer();
            var controller = newController();
            var cursor = newCursor();
            var scoreTitle = newScoreTitle();
            var scoreNumber = newScoreNumber();
            gameScene.addChild(background);
            gameScene.addChild(bear);
            gameScene.addChild(controller);
            gameScene.addChild(cursor);
            gameScene.addChild(scoreTitle);
            gameScene.addChild(scoreNumber);

            var currentInput = INPUT_NONE;

            // ハートをキャッチするたびに増える得点です
            var score = 0;

            // ボールがプレイヤーに当たった時に true になります
            var gameover = false;

            /**
             * ボタン上をタッチまたはスワイプした際に発火する関数です。
             * 以下の処理を行います。
             *
             * - ボタンのスプライトを変更し、押された感じを表現します
             * - プレイヤーのモーションを走っている状態にします
             *
             * @param {Event} e
             */
            var inputCursor = function (e) {
                var input = (e.x < STAGE_WIDTH / 2) ? INPUT_LEFT : INPUT_RIGHT;
                if (currentInput !== input) {
                    currentInput = input;
                    cursor.frame = [input];

                    if (!gameover) {
                        var newScale = (currentInput === INPUT_RIGHT) ? 1 : -1;
                        bear.scaleX = newScale;
                        bear.frame = [0, 0, 1, 1, 0, 0, 2, 2];
                    }
                }
            };
            /**
             * ボタンから指を離した際に発火する関数です。
             * 以下の処理を行います。
             *
             * - ボタンのスプライトをデフォルトに変更します
             * - プレイヤーのモーションを止まっている状態にします
             *
             * @param {Event} e
             */
            var stopCursor = function (e) {
                currentInput = INPUT_NONE;
                cursor.frame = [INPUT_NONE];
                if (!gameover) {
                    bear.frame = [0];
                }
            };
            cursor.addEventListener(Event.TOUCH_START, inputCursor);
            cursor.addEventListener(Event.TOUCH_MOVE, inputCursor);
            cursor.addEventListener(Event.TOUCH_END, stopCursor);

            /**
             * フレーム毎に実行される関数です。
             * もしも右か左のボタンが押されていたら、プレイヤーの位置を移動させます。
             *
             * @param {Event} e
             */
            var moveBear = function (e) {
                if (currentInput === INPUT_NONE) {
                    return;
                }

                var dx = (currentInput === INPUT_LEFT) ? -5 : 5;
                var newX = Math.min(Math.max(bear.x + dx, 0), STAGE_WIDTH - 32);
                bear.x = newX;
            };
            bear.addEventListener(Event.ENTER_FRAME, moveBear);

            var createHeart = function () {
                var width = 32;
                var height = 32;
                var sprite = new Sprite(width, height);
                sprite.image = core.assets["img/heart.png"];
                sprite.x = Math.random() * (STAGE_WIDTH - width);
                var topToBottom = (Math.random() < 0.5); // true: 上から下, false: 下から上
                sprite.y = topToBottom ? -width : STAGE_HEIGHT;
                sprite.frame = [0, 0, 0, 1, 1, 1];
                sprite.addEventListener(Event.ENTER_FRAME, function (e) {
                    if (gameover) {
                        return;
                    }
                    sprite.y += topToBottom ? 3 : -3;
                    var out = (topToBottom && STAGE_HEIGHT < sprite.y) || (!topToBottom && sprite.y < -width);
                    if (out) {
                        gameScene.removeChild(sprite);
                    }
                    // プレイヤーがハートをキャッチしたら得点を +1 します
                    if (sprite.within(bear, width / 2)) {
                        gameScene.removeChild(sprite);
                        score++;
                        scoreNumber.text = score;
                    }
                });
                return sprite;
            };
            var createBall = function (e) {
                var width = 16;
                var height = 16;
                var sprite = new Sprite(width, height);
                sprite.image = core.assets["img/icon1.png"];
                sprite.x = Math.random() * (STAGE_WIDTH - width);
                var topToBottom = (Math.random() < 0.5); // true: 上から下, false: 下から上
                var speed = 2 + (Math.random() * 3);
                sprite.y = topToBottom ? -width : STAGE_HEIGHT;
                var frameIndex = (Math.random() < 0.5) ? 0 : 1;
                sprite.frame = [frameIndex];
                sprite.addEventListener(Event.ENTER_FRAME, function (e) {
                    sprite.rotate(15);
                    if (gameover) {
                        return;
                    }
                    sprite.y += topToBottom ? speed : -speed;
                    var out = (topToBottom && STAGE_HEIGHT < sprite.y) || (!topToBottom && sprite.y < -width);
                    if (out) {
                        gameScene.removeChild(sprite);
                    }
                    // ボールがプレイヤーに当たったらゲームオーバーとします
                    if (sprite.within(bear, width)) {
                        gameover = true;
                        bear.frame = [3];
                        bear.removeEventListener(Event.ENTER_FRAME, moveBear);
                        bear.tl.moveTo(bear.x, STAGE_HEIGHT + 64, 15, function (t, b, c, d) {
                            var peak = 0.25;
                            var x = (t / d) - peak;
                            return 2 * (x * x * (c - b) + b - (peak * peak));
                        });
                        gameScene.removeEventListener(Event.ENTER_FRAME, createObject);
                    }
                });
                return sprite;
            };
            var createObject = function (e) {
                var rand = Math.random();
                if (0.06 < rand) {
                    return;
                }

                if (0.03 < rand) {
                    var heart = createHeart();
                    gameScene.insertBefore(heart, controller);
                } else {
                    var ball = createBall();
                    gameScene.insertBefore(ball, controller);
                }
            };
            gameScene.addEventListener(Event.ENTER_FRAME, createObject);
            core.replaceScene(gameScene);
        };

        startNewGame();
    };
    core.start();
}
<|endoftext|>


<commit_before>'use strict';

// Declare app level module which depends on filters, and services
angular.module('issuesApp', [
  'cfp.hotkeys',
  'firebase',
  'ngRoute',
  'ngAnimate',
  'issuesApp.services',
  'issuesApp.filters',
  'issuesApp.controllers',
  'issuesApp.directives'
]).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
  $locationProvider.html5Mode(true);
  $routeProvider.when('/issues', {templateUrl: 'app/partials/dashboard.html', controller: 'IssuesCtrl'});
  $routeProvider.otherwise({redirectTo: '/issues'});
}]);
<commit_msg>Stop using html5 mode<commit_after>'use strict';

// Declare app level module which depends on filters, and services
angular.module('issuesApp', [
  'cfp.hotkeys',
  'firebase',
  'ngRoute',
  'ngAnimate',
  'issuesApp.services',
  'issuesApp.filters',
  'issuesApp.controllers',
  'issuesApp.directives'
]).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
  $routeProvider.when('/issues', {templateUrl: 'app/partials/dashboard.html', controller: 'IssuesCtrl'});
  $routeProvider.otherwise({redirectTo: '/issues'});
}]);
<|endoftext|>