<commit_before>'use strict';

/**
 * @ngdoc function
 * @name SubSnoopApp.controller:UsersubCtrl
 * @description
 * # UsersubCtrl
 * Controller of the SubSnoopApp
 */
angular.module('SubSnoopApp')
  .controller('UserSubCtrl', ['$rootScope', '$scope', '$routeParams', '$window', '$filter', 'rank', 'subsData', 'search',
    'subFactory', 'sortFactory', '$anchorScroll', '$location', '$timeout', 'subInfo',
    function ($rootScope, $scope, $routeParams, $window, $filter, rank, subsData, search, subFactory, sortFactory, $anchorScroll, $location, $timeout, subInfo) {

    /*
     Initalization
    */
    $window.scrollTo(0, 0);
    $scope.pages = ['comments', 'submissions', 'sub'];
    $scope.page = $scope.pages[2];
    $scope.subreddit = $routeParams.subreddit;
    $scope.username = $routeParams.username;
    $rootScope.title = $scope.username + ' | ' + $scope.subreddit;
    $scope.latestPost = subFactory.getLatestPost($scope.sub);

    /*
     Set up for specific subreddit
     $scope.sub contains the comments and submissions arrays
    */
    $scope.subsArray = Object.keys(subsData.subs);
    $scope.sub = subsData.subs[$scope.subreddit];

    /*
     Determines how many comments/submissions to display on screen
     Default is set to 25
    */
    $scope.views = [10, 25, 50, 100, 'All'];
    var defaultView = 10;

    /*
     Set up for pagination of comments or submissions
    */
    $scope.subPage = {};
    $scope.subPage.items = parseInt(defaultView);
    $scope.subPage.max = 7;
    $scope.subPage.current = 1;
    $scope.sortSelected = sortFactory.getDefaultPostSort();
    $scope.commentSort = sortFactory.getDefaultPostSort();
    $scope.submitSort = sortFactory.getDefaultPostSort();

    /*
     Tab configuration for toggling between comment and submissions display
    */
    $scope.anchor = '';
    $scope.tabOptions = ['comments', 'submissions'];
    $scope.tab = 2;
    $scope.open = true;

    $scope.comments = $scope.sub['comments'];
    $scope.submissions = $scope.sub['submissions'];

    $scope.sliceArray = function(data) {
      return data.slice((($scope.subPage.current-1)*$scope.subPage.items),
        (($scope.subPage.current)*$scope.subPage.items));

    }
    $scope.slicedArray = [];

    /*
     Jump back to top of page after changing pages
    */
    $scope.backUp = function() {
      document.getElementById('table-start').scrollIntoView();
    };

    /*
     Set up the data array to be displayed based on the current tab and sort value.
     By default, comments are displayed first and all data is sorted by most recent.
    */
    $scope.setArray = function(top) {
      if ($scope.tab == 0) {
        $scope.slicedArray = $scope.sliceArray($scope.comments);
      } else {
        $scope.slicedArray = $scope.sliceArray($scope.submissions);
      }

      if (top) {
        $scope.backUp();
      }
    };

    /*
     Set open/closed status of accordions
    */
    $scope.setAccordion = function() {
      $scope.open = $scope.tab === 2 ? true : false;
    };

    /*
     Update tab statics according to what the user clicked on
     Tab options are Subreddits, Overview, Comments, or Submitted
    */
    $scope.setTab = function(num) {
      $scope.tab = parseInt(num);
      $scope.subPage.current = 1;
      $scope.setAccordion();
      $scope.setPage(num);

      if ($scope.tab == 0) {
        $scope.sortSelected = $scope.commentSort;
      } else {
        $scope.sortSelected = $scope.submitSort;
      }

      if ($scope.tab < 2) {
        $scope.setArray();
      }
    };

    /*
     Set the page for pagination
    */
    $scope.setPage = function(num) {
      $scope.page = $scope.pages[num];
    }

    if ($scope.tab == 2) {
      /*
       Call subreddit API and get sub banner and icon
      */
      if ($scope.sub.info == null) {
        $scope.subInfo = subInfo.getData($scope.subreddit).then(function(response) {
          $scope.subInfo = response;
          subFactory.setSubInfo($scope.subreddit, response);
        });
      } else {
        $scope.subInfo = $scope.sub.info;
      }

      $scope.setTab(2);
    }

    /*
     Used for setting how many items to view on screen at a time and also for pagination
    */
    $scope.setItemsPerPage = function(num) {
      $scope.subPage.current = 1;

      if (num === 'All') {
        $scope.subPage.items = $scope.sub[$scope.tabOptions[$scope.tab]].length;
      } else {
        $scope.subPage.items = num;
      }

      $scope.setArray();
    };

    /*
     Check whether the current tab is a certain number
    */
    $scope.isSet = function(num) {
      return $scope.tab === parseInt(num);
    };

    /*
     Get the current tab
    */
    $scope.getActive = function(num) {
      if ($scope.isSet(num)) {
        return { 'active': true };
      }
    };

    /*
     Used for sorting comments/submissions
    */
    $scope.data = sortFactory.getPostSorting();

    $scope.setSortOption = function(sort) {
      $scope.subPage.current = 1;
      $scope.sortSelected = sort;

      if ($scope.tab == 0) {
        $scope.comments = $filter('sortPosts')($scope.sub['comments'], sort.value);
        $scope.commentSort = sort
      } else {
        $scope.submissions = $filter('sortPosts')($scope.sub['submissions'], sort.value);
        $scope.submitSort = sort;
      }

      $scope.setArray();
    };

    /*
     Sort subreddits when side nav is toggled
    */
    $scope.selected = sortFactory.getSubSort();
    $scope.subList = $filter('sortSubs')($scope.subsArray, $scope.selected.value, subsData.subs);
    $scope.changeSubs = function(term) {
      $scope.subList = [];
      $scope.subList = search.findSubs($scope.subsArray, term);
    };

  }
]);
<commit_msg>Fix: Latest post statistic for each sub<commit_after>'use strict';

/**
 * @ngdoc function
 * @name SubSnoopApp.controller:UsersubCtrl
 * @description
 * # UsersubCtrl
 * Controller of the SubSnoopApp
 */
angular.module('SubSnoopApp')
  .controller('UserSubCtrl', ['$rootScope', '$scope', '$routeParams', '$window', '$filter', 'rank', 'subsData', 'search',
    'subFactory', 'sortFactory', '$anchorScroll', '$location', '$timeout', 'subInfo',
    function ($rootScope, $scope, $routeParams, $window, $filter, rank, subsData, search, subFactory, sortFactory, $anchorScroll, $location, $timeout, subInfo) {

    /*
     Initalization
    */
    $window.scrollTo(0, 0);
    $scope.pages = ['comments', 'submissions', 'sub'];
    $scope.page = $scope.pages[2];
    $scope.subreddit = $routeParams.subreddit;
    $scope.username = $routeParams.username;
    $rootScope.title = $scope.username + ' | ' + $scope.subreddit;

    /*
     Set up for specific subreddit
     $scope.sub contains the comments and submissions arrays
    */
    $scope.subsArray = Object.keys(subsData.subs);
    $scope.sub = subsData.subs[$scope.subreddit];
    $scope.latestPost = subFactory.getLatestPost($scope.sub);

    /*
     Determines how many comments/submissions to display on screen
     Default is set to 25
    */
    $scope.views = [10, 25, 50, 100, 'All'];
    var defaultView = 10;

    /*
     Set up for pagination of comments or submissions
    */
    $scope.subPage = {};
    $scope.subPage.items = parseInt(defaultView);
    $scope.subPage.max = 7;
    $scope.subPage.current = 1;
    $scope.sortSelected = sortFactory.getDefaultPostSort();
    $scope.commentSort = sortFactory.getDefaultPostSort();
    $scope.submitSort = sortFactory.getDefaultPostSort();

    /*
     Tab configuration for toggling between comment and submissions display
    */
    $scope.anchor = '';
    $scope.tabOptions = ['comments', 'submissions'];
    $scope.tab = 2;
    $scope.open = true;

    $scope.comments = $scope.sub['comments'];
    $scope.submissions = $scope.sub['submissions'];

    $scope.sliceArray = function(data) {
      return data.slice((($scope.subPage.current-1)*$scope.subPage.items),
        (($scope.subPage.current)*$scope.subPage.items));

    }
    $scope.slicedArray = [];

    /*
     Jump back to top of page after changing pages
    */
    $scope.backUp = function() {
      document.getElementById('table-start').scrollIntoView();
    };

    /*
     Set up the data array to be displayed based on the current tab and sort value.
     By default, comments are displayed first and all data is sorted by most recent.
    */
    $scope.setArray = function(top) {
      if ($scope.tab == 0) {
        $scope.slicedArray = $scope.sliceArray($scope.comments);
      } else {
        $scope.slicedArray = $scope.sliceArray($scope.submissions);
      }

      if (top) {
        $scope.backUp();
      }
    };

    /*
     Set open/closed status of accordions
    */
    $scope.setAccordion = function() {
      $scope.open = $scope.tab === 2 ? true : false;
    };

    /*
     Update tab statics according to what the user clicked on
     Tab options are Subreddits, Overview, Comments, or Submitted
    */
    $scope.setTab = function(num) {
      $scope.tab = parseInt(num);
      $scope.subPage.current = 1;
      $scope.setAccordion();
      $scope.setPage(num);

      if ($scope.tab == 0) {
        $scope.sortSelected = $scope.commentSort;
      } else {
        $scope.sortSelected = $scope.submitSort;
      }

      if ($scope.tab < 2) {
        $scope.setArray();
      }
    };

    /*
     Set the page for pagination
    */
    $scope.setPage = function(num) {
      $scope.page = $scope.pages[num];
    }

    if ($scope.tab == 2) {
      /*
       Call subreddit API and get sub banner and icon
      */
      if ($scope.sub.info == null) {
        $scope.subInfo = subInfo.getData($scope.subreddit).then(function(response) {
          $scope.subInfo = response;
          subFactory.setSubInfo($scope.subreddit, response);
        });
      } else {
        $scope.subInfo = $scope.sub.info;
      }

      $scope.setTab(2);
    }

    /*
     Used for setting how many items to view on screen at a time and also for pagination
    */
    $scope.setItemsPerPage = function(num) {
      $scope.subPage.current = 1;

      if (num === 'All') {
        $scope.subPage.items = $scope.sub[$scope.tabOptions[$scope.tab]].length;
      } else {
        $scope.subPage.items = num;
      }

      $scope.setArray();
    };

    /*
     Check whether the current tab is a certain number
    */
    $scope.isSet = function(num) {
      return $scope.tab === parseInt(num);
    };

    /*
     Get the current tab
    */
    $scope.getActive = function(num) {
      if ($scope.isSet(num)) {
        return { 'active': true };
      }
    };

    /*
     Used for sorting comments/submissions
    */
    $scope.data = sortFactory.getPostSorting();

    $scope.setSortOption = function(sort) {
      $scope.subPage.current = 1;
      $scope.sortSelected = sort;

      if ($scope.tab == 0) {
        $scope.comments = $filter('sortPosts')($scope.sub['comments'], sort.value);
        $scope.commentSort = sort
      } else {
        $scope.submissions = $filter('sortPosts')($scope.sub['submissions'], sort.value);
        $scope.submitSort = sort;
      }

      $scope.setArray();
    };

    /*
     Sort subreddits when side nav is toggled
    */
    $scope.selected = sortFactory.getSubSort();
    $scope.subList = $filter('sortSubs')($scope.subsArray, $scope.selected.value, subsData.subs);
    $scope.changeSubs = function(term) {
      $scope.subList = [];
      $scope.subList = search.findSubs($scope.subsArray, term);
    };

  }
]);
<|endoftext|>


<commit_before>const path = require('path')
const cp = require('child_process')
const fs = require('fs-extra')
const webpack = require('webpack')
const chalk = require('chalk')
const figlet = require('figlet')
const boxen = require('boxen')
const outdent = require('outdent')
const filesize = require('filesize')
const gzipSize = require('gzip-size').sync
const indentString = require('indent-string')
const columnify = require('columnify')
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages')
const prettyMs = require('pretty-ms')
const browserslist = require('browserslist')

const log = {
  ok(...a) { console.log(`::: ${chalk.yellow(...a)}`) },
  warn(...a) { console.error(`!!! ${chalk.yellow(...a)}`) },
  err(...a) { console.error(`!!! ${chalk.red(...a)}`) },
  info(...a) { console.log(`--- ${chalk.blue(...a)}`) },
}

function noop() {}

function coloredBanner(text, colors = ['blue', 'red']) {
  // If the console is small, we show only the logo
  if (text.includes(' accurapp') && process.stdout.columns < 125) {
    text = text.slice(0, -' accurapp'.length)
  }

  const bannerText = text.replace(/\|/g, 'l') // In BigMoney font, 'l' (lowercase L) are much nicer than '|' (pipes)
  const bannerColors = { '$': colors[0], '_': colors[1], '|': colors[1], '\\': colors[1], '/': colors[1] }
  const banner = figlet.textSync(bannerText, { font: 'Big Money-nw' })
  const colored = banner.replace(/[^\s]/g, (c) => chalk[bannerColors[c] || 'white'](c))
  return `\n${colored}`
}

function yellowBox(message) {
  const boxenOptions = {
    padding: 1,
    align: 'center',
    borderColor: 'yellow',
  }

  return boxen(message, boxenOptions)
}

function createOutdatedMessage(outdatedDeps, latestDeps) {
  const outdatedMessages = outdatedDeps.map((dep, i) => {
    const updatedDep = latestDeps.find(latestDep => latestDep.name === dep.name)
    return `${chalk.blue(dep.name)} ${chalk.gray(dep.version)} → ${chalk.green(updatedDep.version)}`
  })

  return outdent`
    ${chalk.yellow('Hey, an update for accurapp is available!')}
    ${outdatedMessages.join('\n')}
    ${chalk.yellow('Run')} ${chalk.cyan('yarn upgrade-interactive --latest')} ${chalk.yellow('to update')}
  `
}

function indent(text, prepend = '  ', firstLinePrepend = prepend) {
  return text
    .split(`\n`)
    .map((line, i) => `${i === 0 ? firstLinePrepend : prepend}${line}`)
    .join(`\n`)
}

function listLine(text, color = i => i) {
  return indent(text, '   ', color('\n • '))
}

function readWebpackConfig() {
  const cwd = process.cwd()
  return require(path.join(cwd, 'webpack.config.js'))
}

/*
 * The webpack "compiler" is a low-level interface to Webpack that lets us listen to
 * some events and provide our own custom messages.
 */
function createWebpackCompiler(onFirstReadyCallback = noop, onError = noop) {
  let compiler
  try {
    const config = readWebpackConfig()
    compiler = webpack(config)
  } catch (err) {
    log.err(`Failed to compile:\n${err.message || err}`)
    process.exit(1)
  }

  // You have changed a file, bundle is now "invalidated", and Webpack is recompiling a bundle
  compiler.hooks.invalid.tap('invalid', (filePath) => {
    const filePathRelative = path.relative(process.cwd(), filePath)
    console.log()
    log.info(`Compiling ${chalk.cyan(filePathRelative)}...`)
  })

  let isFirstCompile = true

  // Webpack has finished recompiling the bundle (whether or not you have warnings or errors)
  compiler.hooks.done.tap('done', (stats) => {
    const statsJson = stats.toJson({ all: false, warnings: true, errors: true })
    const messages = formatWebpackMessages(statsJson)
    const time = prettyMs(statsJson.time)
    const isSuccessful = messages.errors.length + messages.warnings.length === 0

    if (isSuccessful) {
      log.ok(`Compiled successfully in ${chalk.cyan(time)}!`)
    } else if (messages.errors.length > 0) {
      log.err('Errors in compiling:')
      // Only log the first error. Others are often indicative
      // of the same problem, but confuse the reader with noise
      console.log(listLine(messages.errors[0], chalk.red))
      onError()
    } else if (messages.warnings.length > 0) {
      log.warn(`Compiled in ${chalk.cyan(time)} with warnings:`)
      messages.warnings.forEach(message => { console.log(listLine(message, chalk.yellow)) })
    }

    // If the first time compiles, also with warnings,
    // call the onFirstReadyCallback
    if (isFirstCompile && messages.errors.length === 0) {
      onFirstReadyCallback()
      isFirstCompile = false
    }
  })

  return compiler
}

function printFileSizes(webpackStats, appBuild, maxBundleGzipSize = 512 * 1024) {
  const assets = (webpackStats.stats || [webpackStats])
    .map(stats =>
      stats
        .toJson({ all: false, assets: true })
        .assets.filter(asset => /\.(js|css)$/.test(asset.name))
        .map(asset => {
          const fileContents = fs.readFileSync(path.join(appBuild, asset.name))
          const size = fs.statSync(path.join(appBuild, asset.name)).size
          const sizeGzip = gzipSize(fileContents)

          return {
            folder: path.join(path.basename(appBuild), path.dirname(asset.name)),
            name: path.basename(asset.name),
            size,
            sizeGzip,
          }
        })
    )
    .reduce((single, all) => all.concat(single), [])

  assets.sort((a, b) => b.size - a.size)

  const isLarge = asset => path.extname(asset.name) === '.js' && asset.size > maxBundleGzipSize

  const columnData = assets.reduce((columnObj, asset) => {
    const sizeLabel = `${filesize(asset.size)} ${chalk.dim(`(${filesize(asset.sizeGzip)} gzipped)`)}`
    const firstColumn = isLarge(asset) ? chalk.yellow(sizeLabel) : sizeLabel
    const secondColumn = `${chalk.dim(`${asset.folder}${path.sep}`)}${chalk.cyan(asset.name)}`

    columnObj[firstColumn] = secondColumn
    return columnObj
  }, {})

  console.log(
    indentString(
      columnify(columnData, {
        showHeaders: false,
        columnSplitter: '   ',
      }),
      3
    )
  )

  if (assets.some(isLarge)) {
    console.log()
    console.log(chalk.yellow(outdent`
      The bundle size is significantly larger than recommended.
      Consider reducing it with code splitting: https://goo.gl/9VhYWB
      You can also analyze the project dependencies: https://goo.gl/sDmR4n
    `))
  }
}

function extractBrowserslistString() {
  const appDir = process.cwd()
  const browsersListConfig = browserslist.loadConfig({ path: appDir })
  return Array.isArray(browsersListConfig) ? browsersListConfig.join(', ') : browsersListConfig
}

function extractLatestCommitHash() {
  try {
    return cp.execSync('git log -n1 --format=format:"%h"')
  } catch (e) {
    // Probably git is not available, return an empty string instead
    return ''
  }
}

function extractLatestCommitTimestamp() {
  try {
    const unixTimestamp = cp.execSync('git log -n1 --format=format:"%ct"')
    const utcTimestamp = `${unixTimestamp}000`
    return utcTimestamp
  } catch (e) {
    // Probably git is not available, return time of the build instead
    return Date.now()
  }
}

module.exports = {
  log,
  noop,
  coloredBanner,
  yellowBox,
  createOutdatedMessage,
  indent,
  listLine,
  readWebpackConfig,
  createWebpackCompiler,
  printFileSizes,
  extractBrowserslistString,
  extractLatestCommitHash,
  extractLatestCommitTimestamp,
}
<commit_msg>🐛 Fix issue with statsJson missing field<commit_after>const path = require('path')
const cp = require('child_process')
const fs = require('fs-extra')
const webpack = require('webpack')
const chalk = require('chalk')
const figlet = require('figlet')
const boxen = require('boxen')
const outdent = require('outdent')
const filesize = require('filesize')
const gzipSize = require('gzip-size').sync
const indentString = require('indent-string')
const columnify = require('columnify')
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages')
const prettyMs = require('pretty-ms')
const browserslist = require('browserslist')

const log = {
  ok(...a) { console.log(`::: ${chalk.yellow(...a)}`) },
  warn(...a) { console.error(`!!! ${chalk.yellow(...a)}`) },
  err(...a) { console.error(`!!! ${chalk.red(...a)}`) },
  info(...a) { console.log(`--- ${chalk.blue(...a)}`) },
}

function noop() {}

function coloredBanner(text, colors = ['blue', 'red']) {
  // If the console is small, we show only the logo
  if (text.includes(' accurapp') && process.stdout.columns < 125) {
    text = text.slice(0, -' accurapp'.length)
  }

  const bannerText = text.replace(/\|/g, 'l') // In BigMoney font, 'l' (lowercase L) are much nicer than '|' (pipes)
  const bannerColors = { '$': colors[0], '_': colors[1], '|': colors[1], '\\': colors[1], '/': colors[1] }
  const banner = figlet.textSync(bannerText, { font: 'Big Money-nw' })
  const colored = banner.replace(/[^\s]/g, (c) => chalk[bannerColors[c] || 'white'](c))
  return `\n${colored}`
}

function yellowBox(message) {
  const boxenOptions = {
    padding: 1,
    align: 'center',
    borderColor: 'yellow',
  }

  return boxen(message, boxenOptions)
}

function createOutdatedMessage(outdatedDeps, latestDeps) {
  const outdatedMessages = outdatedDeps.map((dep, i) => {
    const updatedDep = latestDeps.find(latestDep => latestDep.name === dep.name)
    return `${chalk.blue(dep.name)} ${chalk.gray(dep.version)} → ${chalk.green(updatedDep.version)}`
  })

  return outdent`
    ${chalk.yellow('Hey, an update for accurapp is available!')}
    ${outdatedMessages.join('\n')}
    ${chalk.yellow('Run')} ${chalk.cyan('yarn upgrade-interactive --latest')} ${chalk.yellow('to update')}
  `
}

function indent(text, prepend = '  ', firstLinePrepend = prepend) {
  return text
    .split(`\n`)
    .map((line, i) => `${i === 0 ? firstLinePrepend : prepend}${line}`)
    .join(`\n`)
}

function listLine(text, color = i => i) {
  return indent(text, '   ', color('\n • '))
}

function readWebpackConfig() {
  const cwd = process.cwd()
  return require(path.join(cwd, 'webpack.config.js'))
}

/*
 * The webpack "compiler" is a low-level interface to Webpack that lets us listen to
 * some events and provide our own custom messages.
 */
function createWebpackCompiler(onFirstReadyCallback = noop, onError = noop) {
  let compiler
  try {
    const config = readWebpackConfig()
    compiler = webpack(config)
  } catch (err) {
    log.err(`Failed to compile:\n${err.message || err}`)
    process.exit(1)
  }

  // You have changed a file, bundle is now "invalidated", and Webpack is recompiling a bundle
  compiler.hooks.invalid.tap('invalid', (filePath) => {
    const filePathRelative = path.relative(process.cwd(), filePath)
    console.log()
    log.info(`Compiling ${chalk.cyan(filePathRelative)}...`)
  })

  let isFirstCompile = true

  // Webpack has finished recompiling the bundle (whether or not you have warnings or errors)
  compiler.hooks.done.tap('done', (stats) => {
    const statsJson = stats.toJson({
      all: false,
      warnings: true,
      errors: true,
      timings: true,
    })

    const messages = formatWebpackMessages(statsJson)
    const time = prettyMs(statsJson.time)
    const isSuccessful = messages.errors.length + messages.warnings.length === 0

    if (isSuccessful) {
      log.ok(`Compiled successfully in ${chalk.cyan(time)}!`)
    } else if (messages.errors.length > 0) {
      log.err('Errors in compiling:')
      // Only log the first error. Others are often indicative
      // of the same problem, but confuse the reader with noise
      console.log(listLine(messages.errors[0], chalk.red))
      onError()
    } else if (messages.warnings.length > 0) {
      log.warn(`Compiled in ${chalk.cyan(time)} with warnings:`)
      messages.warnings.forEach(message => { console.log(listLine(message, chalk.yellow)) })
    }

    // If the first time compiles, also with warnings,
    // call the onFirstReadyCallback
    if (isFirstCompile && messages.errors.length === 0) {
      onFirstReadyCallback()
      isFirstCompile = false
    }
  })

  return compiler
}

function printFileSizes(webpackStats, appBuild, maxBundleGzipSize = 512 * 1024) {
  const assets = (webpackStats.stats || [webpackStats])
    .map(stats =>
      stats
        .toJson({ all: false, assets: true })
        .assets.filter(asset => /\.(js|css)$/.test(asset.name))
        .map(asset => {
          const fileContents = fs.readFileSync(path.join(appBuild, asset.name))
          const size = fs.statSync(path.join(appBuild, asset.name)).size
          const sizeGzip = gzipSize(fileContents)

          return {
            folder: path.join(path.basename(appBuild), path.dirname(asset.name)),
            name: path.basename(asset.name),
            size,
            sizeGzip,
          }
        })
    )
    .reduce((single, all) => all.concat(single), [])

  assets.sort((a, b) => b.size - a.size)

  const isLarge = asset => path.extname(asset.name) === '.js' && asset.size > maxBundleGzipSize

  const columnData = assets.reduce((columnObj, asset) => {
    const sizeLabel = `${filesize(asset.size)} ${chalk.dim(`(${filesize(asset.sizeGzip)} gzipped)`)}`
    const firstColumn = isLarge(asset) ? chalk.yellow(sizeLabel) : sizeLabel
    const secondColumn = `${chalk.dim(`${asset.folder}${path.sep}`)}${chalk.cyan(asset.name)}`

    columnObj[firstColumn] = secondColumn
    return columnObj
  }, {})

  console.log(
    indentString(
      columnify(columnData, {
        showHeaders: false,
        columnSplitter: '   ',
      }),
      3
    )
  )

  if (assets.some(isLarge)) {
    console.log()
    console.log(chalk.yellow(outdent`
      The bundle size is significantly larger than recommended.
      Consider reducing it with code splitting: https://goo.gl/9VhYWB
      You can also analyze the project dependencies: https://goo.gl/sDmR4n
    `))
  }
}

function extractBrowserslistString() {
  const appDir = process.cwd()
  const browsersListConfig = browserslist.loadConfig({ path: appDir })
  return Array.isArray(browsersListConfig) ? browsersListConfig.join(', ') : browsersListConfig
}

function extractLatestCommitHash() {
  try {
    return cp.execSync('git log -n1 --format=format:"%h"')
  } catch (e) {
    // Probably git is not available, return an empty string instead
    return ''
  }
}

function extractLatestCommitTimestamp() {
  try {
    const unixTimestamp = cp.execSync('git log -n1 --format=format:"%ct"')
    const utcTimestamp = `${unixTimestamp}000`
    return utcTimestamp
  } catch (e) {
    // Probably git is not available, return time of the build instead
    return Date.now()
  }
}

module.exports = {
  log,
  noop,
  coloredBanner,
  yellowBox,
  createOutdatedMessage,
  indent,
  listLine,
  readWebpackConfig,
  createWebpackCompiler,
  printFileSizes,
  extractBrowserslistString,
  extractLatestCommitHash,
  extractLatestCommitTimestamp,
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

function sendSyncMessage(msg) {
  return JSON.parse(extension.internal.sendSyncMessage(JSON.stringify(msg)));
}

function daysOfWeekToFlag(days) {
  var flag = 0;
  if (days instanceof Array && days.length > 0) {
    for (var i = 0, len = days.length; i < len; i++) {
      var day = days[i];
      if (day === 'SU')
        flag |= 0x01;
      else if (day === 'MO')
        flag |= 0x02;
      else if (day === 'TU')
        flag |= 0x04;
      else if (day === 'WE')
        flag |= 0x08;
      else if (day === 'TH')
        flag |= 0x10;
      else if (day === 'FR')
        flag |= 0x20;
      else if (day === 'SA')
        flag |= 0x40;
    }
  }

  return flag;
}

function flagToDaysOfWeek(flag) {
  var days = [];
  if (flag & 0x01)
    days.push('SU');
  if (flag & 0x02)
    days.push('MO');
  if (flag & 0x04)
    days.push('TU');
  if (flag & 0x08)
    days.push('WE');
  if (flag & 0x10)
    days.push('TH');
  if (flag & 0x20)
    days.push('FR');
  if (flag & 0x40)
    days.push('SA');

  return days;
}

function defineReadOnlyProperty(object, key, value) {
  Object.defineProperty(object, key, {
    enumerable: true,
    writable: false,
    value: value
  });
}

var OperationEnum = {
  AddAlarmAbs: 'alarm.add.absolute',
  AddAlarmRel: 'alarm.add.relative',
  GetRemainingSec: 'alarm.get.remainingsec',
  GetNextScheduledDate: 'alarm.get.nextScheduledDate',
  RemoveAlarm: 'alarm.remove',
  RemoveAllAlarm: 'alarm.removeAll',
  GetAlarm: 'alarm.getInfo',
  GetAllAlarms: 'alarm.getAllInfo'
};

defineReadOnlyProperty(exports, 'PERIOD_MINUTE', 60);
defineReadOnlyProperty(exports, 'PERIOD_HOUR', 3600);
defineReadOnlyProperty(exports, 'PERIOD_DAY', 86400);
defineReadOnlyProperty(exports, 'PERIOD_WEEK', 604800);

tizen.Alarm = function() {};
tizen.Alarm.prototype.constructor = tizen.Alarm;

tizen.AlarmAbsolute = function(date, periodOrDaysOfWeek) {
  tizen.Alarm.apply(this);

  if (date instanceof Date) {
    defineReadOnlyProperty(this, 'date', date);
  } else {
    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
  }

  var periodValue = null;
  var daysOfTheWeek = [];
  if (typeof periodOrDaysOfWeek === 'number' && !isNaN(periodOrDaysOfWeek)) {
    periodValue = periodOrDaysOfWeek;
  } else if (periodOrDaysOfWeek instanceof Array && periodOrDaysOfWeek.length > 0) {
    daysOfTheWeek = periodOrDaysOfWeek;
  }
  defineReadOnlyProperty(this, 'period', periodValue);
  defineReadOnlyProperty(this, 'daysOfTheWeek', daysOfTheWeek);
};

tizen.AlarmAbsolute.prototype = new tizen.Alarm();
tizen.AlarmAbsolute.prototype.constructor = tizen.AlarmAbsolute;

tizen.AlarmAbsolute.prototype.getNextScheduledDate = function() {
  if (this.id === undefined) {
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
  }

  var operation = { cmd: OperationEnum.GetNextScheduledDate, alarm: this.id };
  var ret = sendSyncMessage(operation);
  if (ret.error) {
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
  }

  var seconds = ret.data['nextScheduledDate'] || 0;
  return new Date(seconds * 1000);
};

tizen.AlarmRelative = function(delay, period) {
  tizen.Alarm.apply(this);

  if (typeof delay === 'number' && !isNaN(delay))
    defineReadOnlyProperty(this, 'delay', delay);
  else
    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);

  if (typeof period === 'number' && !isNaN(period))
    defineReadOnlyProperty(this, 'period', period);
  else
    defineReadOnlyProperty(this, 'period', null);
};

tizen.AlarmRelative.prototype = new tizen.Alarm();
tizen.AlarmRelative.prototype.constructor = tizen.AlarmRelative;

tizen.AlarmRelative.prototype.getRemainingSeconds = function() {
  if (this.id === undefined)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);

  var operation = { cmd: OperationEnum.GetRemainingSec, alarm: this.id };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);

  return ret.data['remainingSeconds'];
};

exports.add = function(alarm, applicationId, appControl) {
  var cmd = undefined;
  var alarmInfo = {};
  if (alarm instanceof tizen.AlarmAbsolute) {
    cmd = OperationEnum.AddAlarmAbs;
    // Convert milliseconds to seconds and round it.
    alarmInfo['date'] = Math.floor(alarm.date.getTime() / 1000 + 0.5);
    alarmInfo['period'] = alarm.period || 0;
    alarmInfo['daysOfTheWeek'] = daysOfWeekToFlag(alarm.daysOfTheWeek);
  } else if (alarm instanceof tizen.AlarmRelative) {
    cmd = OperationEnum.AddAlarmRel;
    alarmInfo['delay'] = alarm.delay;
    alarmInfo['period'] = alarm.period || 0;
  } else {
    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
  }

  var operation = {
    cmd: cmd,
    alarm: alarmInfo,
    applicationId: applicationId,
    appControl: appControl
  };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);

  defineReadOnlyProperty(alarm, 'id', ret.data['id']);
};

exports.remove = function(alarmId) {
  var operation = { cmd: OperationEnum.RemoveAlarm, alarm: alarmId };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
  console.debug('Succeed to remove alarm ' + alarmId);
};

exports.removeAll = function() {
  var operation = { cmd: OperationEnum.RemoveAllAlarm };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
  console.debug('Succeed to remove all alarms');
};

function parseAlarm(data) {
  var alarm = null;
  var obj = JSON.parse(data);

  if (obj['type'] === 'absolute') {
    // Convert seconds to milliseconds and use it to create Date object.
    var date = new Date(obj['date'] * 1000);
    var daysOfTheWeek = flagToDaysOfWeek(obj['weekFlag']);
    alarm = new tizen.AlarmAbsolute(date, daysOfTheWeek.length > 0 ? daysOfTheWeek : obj['period']);
    defineReadOnlyProperty(alarm, 'id', obj['id']);
  } else if (obj['type'] === 'relative') {
    alarm = new tizen.AlarmRelative(obj['delay'], obj['period']);
    defineReadOnlyProperty(alarm, 'id', obj['id']);
  }

  return alarm;
}

exports.get = function(alarmId) {
  var operation = { cmd: OperationEnum.GetAlarm, alarm: alarmId };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
  else if (!ret.data)
    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);

  return parseAlarm(ret.data);
};

exports.getAll = function() {
  var operation = { cmd: OperationEnum.GetAllAlarms };
  var ret = sendSyncMessage(operation);
  if (ret.error || !ret.data)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);

  var alarms = [];
  for (var i = 0, len = ret.data.length; i < len; i++) {
    var alarm = parseAlarm(ret.data[i]);
    alarms.push(alarm);
  }
  return alarms;
};
<commit_msg>[Alarm] Initialize the "id" to null in constructor The alarm id becomes valid only when it's added into tizen system. Before that we should ensure the property is enumerable. Set the configurable to true because we can re-define the property later in sub class when it's added into tizen system.<commit_after>// Copyright (c) 2014 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

function sendSyncMessage(msg) {
  return JSON.parse(extension.internal.sendSyncMessage(JSON.stringify(msg)));
}

function daysOfWeekToFlag(days) {
  var flag = 0;
  if (days instanceof Array && days.length > 0) {
    for (var i = 0, len = days.length; i < len; i++) {
      var day = days[i];
      if (day === 'SU')
        flag |= 0x01;
      else if (day === 'MO')
        flag |= 0x02;
      else if (day === 'TU')
        flag |= 0x04;
      else if (day === 'WE')
        flag |= 0x08;
      else if (day === 'TH')
        flag |= 0x10;
      else if (day === 'FR')
        flag |= 0x20;
      else if (day === 'SA')
        flag |= 0x40;
    }
  }

  return flag;
}

function flagToDaysOfWeek(flag) {
  var days = [];
  if (flag & 0x01)
    days.push('SU');
  if (flag & 0x02)
    days.push('MO');
  if (flag & 0x04)
    days.push('TU');
  if (flag & 0x08)
    days.push('WE');
  if (flag & 0x10)
    days.push('TH');
  if (flag & 0x20)
    days.push('FR');
  if (flag & 0x40)
    days.push('SA');

  return days;
}

function defineReadOnlyProperty(object, key, value, configurable) {
  configurable = configurable || false;
  Object.defineProperty(object, key, {
    configurable: configurable,
    enumerable: true,
    writable: false,
    value: value
  });
}

var OperationEnum = {
  AddAlarmAbs: 'alarm.add.absolute',
  AddAlarmRel: 'alarm.add.relative',
  GetRemainingSec: 'alarm.get.remainingsec',
  GetNextScheduledDate: 'alarm.get.nextScheduledDate',
  RemoveAlarm: 'alarm.remove',
  RemoveAllAlarm: 'alarm.removeAll',
  GetAlarm: 'alarm.getInfo',
  GetAllAlarms: 'alarm.getAllInfo'
};

defineReadOnlyProperty(exports, 'PERIOD_MINUTE', 60);
defineReadOnlyProperty(exports, 'PERIOD_HOUR', 3600);
defineReadOnlyProperty(exports, 'PERIOD_DAY', 86400);
defineReadOnlyProperty(exports, 'PERIOD_WEEK', 604800);

tizen.Alarm = function() {
  // set configurable as true so that this property can be re-defined in sub class
  defineReadOnlyProperty(this, 'id', null, true);
};
tizen.Alarm.prototype.constructor = tizen.Alarm;

tizen.AlarmAbsolute = function(date, periodOrDaysOfWeek) {
  tizen.Alarm.apply(this);

  if (date instanceof Date) {
    defineReadOnlyProperty(this, 'date', date);
  } else {
    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
  }

  var periodValue = null;
  var daysOfTheWeek = [];
  if (typeof periodOrDaysOfWeek === 'number' && !isNaN(periodOrDaysOfWeek)) {
    periodValue = periodOrDaysOfWeek;
  } else if (periodOrDaysOfWeek instanceof Array && periodOrDaysOfWeek.length > 0) {
    daysOfTheWeek = periodOrDaysOfWeek;
  }
  defineReadOnlyProperty(this, 'period', periodValue);
  defineReadOnlyProperty(this, 'daysOfTheWeek', daysOfTheWeek);
};

tizen.AlarmAbsolute.prototype = new tizen.Alarm();
tizen.AlarmAbsolute.prototype.constructor = tizen.AlarmAbsolute;

tizen.AlarmAbsolute.prototype.getNextScheduledDate = function() {
  if (this.id === undefined) {
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
  }

  var operation = { cmd: OperationEnum.GetNextScheduledDate, alarm: this.id };
  var ret = sendSyncMessage(operation);
  if (ret.error) {
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
  }

  var seconds = ret.data['nextScheduledDate'] || 0;
  return new Date(seconds * 1000);
};

tizen.AlarmRelative = function(delay, period) {
  tizen.Alarm.apply(this);

  if (typeof delay === 'number' && !isNaN(delay))
    defineReadOnlyProperty(this, 'delay', delay);
  else
    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);

  if (typeof period === 'number' && !isNaN(period))
    defineReadOnlyProperty(this, 'period', period);
  else
    defineReadOnlyProperty(this, 'period', null);
};

tizen.AlarmRelative.prototype = new tizen.Alarm();
tizen.AlarmRelative.prototype.constructor = tizen.AlarmRelative;

tizen.AlarmRelative.prototype.getRemainingSeconds = function() {
  if (this.id === undefined)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);

  var operation = { cmd: OperationEnum.GetRemainingSec, alarm: this.id };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);

  return ret.data['remainingSeconds'];
};

exports.add = function(alarm, applicationId, appControl) {
  var cmd = undefined;
  var alarmInfo = {};
  if (alarm instanceof tizen.AlarmAbsolute) {
    cmd = OperationEnum.AddAlarmAbs;
    // Convert milliseconds to seconds and round it.
    alarmInfo['date'] = Math.floor(alarm.date.getTime() / 1000 + 0.5);
    alarmInfo['period'] = alarm.period || 0;
    alarmInfo['daysOfTheWeek'] = daysOfWeekToFlag(alarm.daysOfTheWeek);
  } else if (alarm instanceof tizen.AlarmRelative) {
    cmd = OperationEnum.AddAlarmRel;
    alarmInfo['delay'] = alarm.delay;
    alarmInfo['period'] = alarm.period || 0;
  } else {
    throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
  }

  var operation = {
    cmd: cmd,
    alarm: alarmInfo,
    applicationId: applicationId,
    appControl: appControl
  };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);

  defineReadOnlyProperty(alarm, 'id', ret.data['id']);
};

exports.remove = function(alarmId) {
  var operation = { cmd: OperationEnum.RemoveAlarm, alarm: alarmId };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
  console.debug('Succeed to remove alarm ' + alarmId);
};

exports.removeAll = function() {
  var operation = { cmd: OperationEnum.RemoveAllAlarm };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);
  console.debug('Succeed to remove all alarms');
};

function parseAlarm(data) {
  var alarm = null;
  var obj = JSON.parse(data);

  if (obj['type'] === 'absolute') {
    // Convert seconds to milliseconds and use it to create Date object.
    var date = new Date(obj['date'] * 1000);
    var daysOfTheWeek = flagToDaysOfWeek(obj['weekFlag']);
    alarm = new tizen.AlarmAbsolute(date, daysOfTheWeek.length > 0 ? daysOfTheWeek : obj['period']);
    defineReadOnlyProperty(alarm, 'id', obj['id']);
  } else if (obj['type'] === 'relative') {
    alarm = new tizen.AlarmRelative(obj['delay'], obj['period']);
    defineReadOnlyProperty(alarm, 'id', obj['id']);
  }

  return alarm;
}

exports.get = function(alarmId) {
  var operation = { cmd: OperationEnum.GetAlarm, alarm: alarmId };
  var ret = sendSyncMessage(operation);
  if (ret.error)
    throw new tizen.WebAPIException(tizen.WebAPIException.NOT_FOUND_ERR);
  else if (!ret.data)
    throw new tizen.WebAPIException(tizen.WebAPIException.INVALID_VALUES_ERR);

  return parseAlarm(ret.data);
};

exports.getAll = function() {
  var operation = { cmd: OperationEnum.GetAllAlarms };
  var ret = sendSyncMessage(operation);
  if (ret.error || !ret.data)
    throw new tizen.WebAPIException(tizen.WebAPIException.UNKNOWN_ERR);

  var alarms = [];
  for (var i = 0, len = ret.data.length; i < len; i++) {
    var alarm = parseAlarm(ret.data[i]);
    alarms.push(alarm);
  }
  return alarms;
};
<|endoftext|>


<commit_before>const prefix = '_async_computed_'

export default {
  install (Vue, options) {
    Vue.mixin({
      created () {
        Object.keys(this.$options.asyncComputed || {}).forEach(key => {
          const fn = this.$options.asyncComputed[key]
          if (!this.$options.computed) this.$options.computed = {}
          Vue.set(this.$options.computed, prefix + key, fn)
          Vue.set(this.$data, key, null)
        })

        this._initComputed()

        Object.keys(this.$options.asyncComputed || {}).forEach(key => {
          let promiseId = 0
          this.$watch(prefix + key, newPromise => {
            const thisPromise = ++promiseId
            newPromise.then(value => {
              if (thisPromise !== promiseId) return
              this[key] = value
            }).catch(err => {
              throw err
            })
          }, { immediate: true })
        })
      }
    })
  }
}
<commit_msg>Change prefix<commit_after>const prefix = '_async_computed$'

export default {
  install (Vue, options) {
    Vue.mixin({
      created () {
        Object.keys(this.$options.asyncComputed || {}).forEach(key => {
          const fn = this.$options.asyncComputed[key]
          if (!this.$options.computed) this.$options.computed = {}
          Vue.set(this.$options.computed, prefix + key, fn)
          Vue.set(this.$data, key, null)
        })

        this._initComputed()

        Object.keys(this.$options.asyncComputed || {}).forEach(key => {
          let promiseId = 0
          this.$watch(prefix + key, newPromise => {
            const thisPromise = ++promiseId
            newPromise.then(value => {
              if (thisPromise !== promiseId) return
              this[key] = value
            }).catch(err => {
              throw err
            })
          }, { immediate: true })
        })
      }
    })
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2017 CA. All rights reserved.
 * This software may be modified and distributed under the terms
 * of the MIT license. See the LICENSE file for details.
 */

import baseConfig from './base';

export default baseConfig;
<commit_msg>chore: include all extensions in default export<commit_after>/**
 * Copyright (c) 2017 CA. All rights reserved.
 * This software may be modified and distributed under the terms
 * of the MIT license. See the LICENSE file for details.
 */

import { resolve } from 'path';
import Config from 'webpack-config';

export default new Config().extend(
  resolve(__dirname, 'base.js'),
  resolve(__dirname, 'css.js'),
  resolve(__dirname, 'scss.js'),
  resolve(__dirname, 'fontgen.js'),
  resolve(__dirname, 'eslint.js'),
  resolve(__dirname, 'flowStatus.js'),
  resolve(__dirname, 'production.js'),
);
<|endoftext|>


<commit_before>(function () {
  function SongPlayer(Fixtures) {
    var SongPlayer = {};

    /**
    * @desc Storing album information
    * @type {Object}
    */
    var currentAlbum = Fixtures.getAlbum();

    /**
    * @desc Buzz object audio file
    * @type {Object}
    */
    var currentBuzzObject = null;

    /**
    * @function setSong
    * @desc Stops currently playing song and loads new audio file as currentBuzzObject
    * @param {Object} song
    */
    var setSong = function(song) {
      if (currentBuzzObject) {
        currentBuzzObject.stop();
        SongPlayer.currentSong.playing = null;
      }

      currentBuzzObject = new buzz.sound(song.audioUrl, {
        formats: ['mp3'],
        preload: true
      });

      SongPlayer.currentSong = song;
    };

    /**
    * @function playSong
    * @desc plays sellected song
    * @param {Object} song
    */
    var playSong = function(song) {
      currentBuzzObject.play();
      song.playing = true;
    };

    /**
    * @function stopSong
    * @desc stops currently playing song
    * @param {Object} song
    */
    var stopSong = function(song) {
      currentBuzzObject.stop();
      SongPlayer.currentSong.playing = null;
    };

    /**
    * @function getSongIndex
    * @desc retrieves the index of song
    * @param {Object} song
    */
    var getSongIndex = function(song) {
      return currentAlbum.songs.indexOf(song);
    };

    /**
   * @desc Active song object from list of songs
   * @type {Object}
   */
    SongPlayer.currentSong = null;

    /**
    * @function SongPlayer.play
    * @desc plays sellected song
    * @param {Object} song
    */
    SongPlayer.play = function(song) {
      song = song || SongPlayer.currentSong;
      if (SongPlayer.currentSong !== song) {
        setSong(song);
        playSong(song);
      } else if (SongPlayer.currentSong === song) {
        if (currentBuzzObject.isPaused()) {
          currentBuzzObject.play();
        }
      }
    };

    /**
    * @function SongPlayer.pause
    * @desc pauses sellected song
    * @param {Object} song
    */
    SongPlayer.pause = function(song) {
      song = song || SongPlayer.currentSong;
      currentBuzzObject.pause();
      song.playing = false;
    };

    /**
    * @function SongPlayer.previous
    * @desc determines current song index, then decreases that index by one
    * @param {Object} song
    */
    SongPlayer.previous = function() {
      var currentSongIndex = getSongIndex(SongPlayer.currentSong);
      currentSongIndex--;

      if (currentSongIndex < 0) {
        stopSong(song);
      } else {
        var song = currentAlbum.songs[currentSongIndex];
        setSong(song);
        playSong(song);
      }
    }

<<<<<<< HEAD
  return SongPlayer;
=======
    /**
   * @function SongPlayer.next
   * @desc determines current song index, then increases that index by one
   * @param {Object} song
   */
   SongPlayer.next = function() {
     var currentSongIndex = getSongIndex(SongPlayer.currentSong);
     currentSongIndex++;

     if (currentSongIndex >= currentAlbum.songs.length) {
       stopSong(song);
     } else {
       var song = currentAlbum.songs[currentSongIndex];
       setSong(song);
       playSong(song);
     }
   };

   return SongPlayer;
>>>>>>> assignment-8-services
  }

  angular
    .module('blocJams')
    .factory('SongPlayer', ['Fixtures', SongPlayer]);
})();
<commit_msg>add ;<commit_after>(function () {
  function SongPlayer(Fixtures) {
    var SongPlayer = {};

    /**
    * @desc Storing album information
    * @type {Object}
    */
    var currentAlbum = Fixtures.getAlbum();

    /**
    * @desc Buzz object audio file
    * @type {Object}
    */
    var currentBuzzObject = null;

    /**
    * @function setSong
    * @desc Stops currently playing song and loads new audio file as currentBuzzObject
    * @param {Object} song
    */
    var setSong = function(song) {
      if (currentBuzzObject) {
        currentBuzzObject.stop();
        SongPlayer.currentSong.playing = null;
      }

      currentBuzzObject = new buzz.sound(song.audioUrl, {
        formats: ['mp3'],
        preload: true
      });

      SongPlayer.currentSong = song;
    };

    /**
    * @function playSong
    * @desc plays sellected song
    * @param {Object} song
    */
    var playSong = function(song) {
      currentBuzzObject.play();
      song.playing = true;
    };

    /**
    * @function stopSong
    * @desc stops currently playing song
    * @param {Object} song
    */
    var stopSong = function(song) {
      currentBuzzObject.stop();
      SongPlayer.currentSong.playing = null;
    };

    /**
    * @function getSongIndex
    * @desc retrieves the index of song
    * @param {Object} song
    */
    var getSongIndex = function(song) {
      return currentAlbum.songs.indexOf(song);
    };

    /**
   * @desc Active song object from list of songs
   * @type {Object}
   */
    SongPlayer.currentSong = null;

    /**
    * @function SongPlayer.play
    * @desc plays sellected song
    * @param {Object} song
    */
    SongPlayer.play = function(song) {
      song = song || SongPlayer.currentSong;
      if (SongPlayer.currentSong !== song) {
        setSong(song);
        playSong(song);
      } else if (SongPlayer.currentSong === song) {
        if (currentBuzzObject.isPaused()) {
          currentBuzzObject.play();
        }
      }
    };

    /**
    * @function SongPlayer.pause
    * @desc pauses sellected song
    * @param {Object} song
    */
    SongPlayer.pause = function(song) {
      song = song || SongPlayer.currentSong;
      currentBuzzObject.pause();
      song.playing = false;
    };

    /**
    * @function SongPlayer.previous
    * @desc determines current song index, then decreases that index by one
    * @param {Object} song
    */
    SongPlayer.previous = function() {
      var currentSongIndex = getSongIndex(SongPlayer.currentSong);
      currentSongIndex--;

      if (currentSongIndex < 0) {
        stopSong(song);
      } else {
        var song = currentAlbum.songs[currentSongIndex];
        setSong(song);
        playSong(song);
      }
    };

    /**
   * @function SongPlayer.next
   * @desc determines current song index, then increases that index by one
   * @param {Object} song
   */
   SongPlayer.next = function() {
     var currentSongIndex = getSongIndex(SongPlayer.currentSong);
     currentSongIndex++;

     if (currentSongIndex >= currentAlbum.songs.length) {
       stopSong(song);
     } else {
       var song = currentAlbum.songs[currentSongIndex];
       setSong(song);
       playSong(song);
     }
   };

   return SongPlayer;

  }

  angular
    .module('blocJams')
    .factory('SongPlayer', ['Fixtures', SongPlayer]);
})();
<|endoftext|>


<commit_before>function getFunctionName (fn) {
  return fn.name || fn.toString().match(/function (.*?)\s*\(/)[1]
}

function getFunctionTypeName (fn) {
  return fn.toJSON ? fn.toJSON() : getFunctionName(fn)
}

function getTypeName (value) {
  if (nativeTypes.Null(value)) return ''

  return getFunctionName(value.constructor)
}

function tfErrorString (typeName, value) {
  var valueType = getTypeName(value)

  return 'Expected ' + typeName + ', got ' + (valueType && valueType + ' ') + JSON.stringify(value)
}

function tfPropertyErrorString (type, name, value) {
  var typeName

  if (nativeTypes.Function(type)) {
    typeName = getFunctionTypeName(type)

  } else if (nativeTypes.Object(type)) {
    typeName = JSON.stringify(type)

  } else if (nativeTypes.String(type)) {
    typeName = type
  }

  return tfErrorString('property \"' + name + '\" of type ' + typeName, value)
}

var nativeTypes = {
  Array (value) { return value !== null && value !== undefined && value.constructor === Array },
  Boolean (value) { return typeof value === 'boolean' },
  Buffer (value) { return Buffer.isBuffer(value) },
  Function (value) { return typeof value === 'function' },
  Null (value) { return value === undefined || value === null },
  Number (value) { return typeof value === 'number' },
  Object (value) { return typeof value === 'object' },
  String (value) { return typeof value === 'string' },
  '' () { return true }
}

var otherTypes = {
  arrayOf (type) {
    function arrayOf (value, strict) {
      try {
        return nativeTypes.Array(value) && value.every(x => typeforce(type, x, strict))

      } catch (e) {
        return false
      }
    }
    arrayOf.toJSON = function () { return '[' + JSON.stringify(type) + ']' }

    return arrayOf
  },

  maybe (type) {
    function maybe (value, strict) {
      return nativeTypes.Null(value, strict) || typeforce(type, value, strict)
    }
    maybe.toJSON = function () { return '?' + (type.toJSON && type.toJSON() || JSON.stringify(type)) }

    return maybe
  },

  object (type) {
    function object (value, strict) {
      typeforce(nativeTypes.Object, value, strict)

      var propertyName, propertyType, propertyValue

      try {
        for (propertyName in type) {
          propertyType = type[propertyName]
          propertyValue = value[propertyName]

          typeforce(propertyType, propertyValue, strict)
        }

      } catch (e) {
        throw new TypeError(tfPropertyErrorString(propertyType, propertyName, propertyValue))
      }

      if (strict) {
        for (propertyName in value) {
          if (type[propertyName]) continue

          throw new TypeError('Unexpected property "' + propertyName + '"')
        }
      }

      return true
    }
    object.toJSON = function () { return JSON.stringify(type) }

    return object
  },

  oneOf (types) {
    return function oneOf (value, strict) {
      return types.some(type => {
        try {
          return typeforce(type, value, strict)

        } catch (e) {
          return false
        }
      })
    }
  },

  compile (type) {
    if (nativeTypes.String(type)) {
      if (type[0] === '?') {
        type = type.slice(1)

        return otherTypes.maybe(otherTypes.compile(type))
      }

      var nativeType = nativeTypes[type]
      if (nativeType) return nativeType

    } else if (nativeTypes.Object(type)) {
      if (nativeTypes.Array(type)) {
        return otherTypes.arrayOf(otherTypes.compile(type[0]))
      }

      var compiled = {}

      for (var propertyName in type) {
        compiled[propertyName] = otherTypes.compile(type[propertyName])
      }

      return compiled
    }

    return type
  },

  value (expected) {
    return function value (actual) {
      return actual === expected
    }
  }
}

function typeforce (type, value, strict) {
  switch (typeof type) {
    case 'function':
      if (type(value, strict)) return true

      throw new TypeError(tfErrorString(getFunctionTypeName(type), value))

    case 'object':
      if (nativeTypes.Array(type)) return typeforce(otherTypes.arrayOf(type[0]), value, strict)

      return typeforce(otherTypes.object(type), value, strict)

    case 'string':
      if (type[0] === '?') {
        type = type.slice(1)

        return typeforce(otherTypes.maybe(type), value, strict)
      }

      var tfType = nativeTypes[type]
      if (tfType) return typeforce(tfType, value, strict)
      if (type === getTypeName(value)) return true

      break
  }

  // catch all
  throw new TypeError(tfErrorString(type, value))
}

// assign all types to typeforce function
var typeName
Object.keys(nativeTypes).forEach(typeName => {
  var nativeType = nativeTypes[typeName]
  nativeType.toJSON = () => typeName

  typeforce[typeName] = nativeType
})

for (typeName in otherTypes) {
  typeforce[typeName] = otherTypes[typeName]
}

module.exports = typeforce
<commit_msg>Null doesnt have a strict param<commit_after>function getFunctionName (fn) {
  return fn.name || fn.toString().match(/function (.*?)\s*\(/)[1]
}

function getFunctionTypeName (fn) {
  return fn.toJSON ? fn.toJSON() : getFunctionName(fn)
}

function getTypeName (value) {
  if (nativeTypes.Null(value)) return ''

  return getFunctionName(value.constructor)
}

function tfErrorString (typeName, value) {
  var valueType = getTypeName(value)

  return 'Expected ' + typeName + ', got ' + (valueType && valueType + ' ') + JSON.stringify(value)
}

function tfPropertyErrorString (type, name, value) {
  var typeName

  if (nativeTypes.Function(type)) {
    typeName = getFunctionTypeName(type)

  } else if (nativeTypes.Object(type)) {
    typeName = JSON.stringify(type)

  } else if (nativeTypes.String(type)) {
    typeName = type
  }

  return tfErrorString('property \"' + name + '\" of type ' + typeName, value)
}

var nativeTypes = {
  Array (value) { return value !== null && value !== undefined && value.constructor === Array },
  Boolean (value) { return typeof value === 'boolean' },
  Buffer (value) { return Buffer.isBuffer(value) },
  Function (value) { return typeof value === 'function' },
  Null (value) { return value === undefined || value === null },
  Number (value) { return typeof value === 'number' },
  Object (value) { return typeof value === 'object' },
  String (value) { return typeof value === 'string' },
  '' () { return true }
}

var otherTypes = {
  arrayOf (type) {
    function arrayOf (value, strict) {
      try {
        return nativeTypes.Array(value) && value.every(x => typeforce(type, x, strict))

      } catch (e) {
        return false
      }
    }
    arrayOf.toJSON = function () { return '[' + JSON.stringify(type) + ']' }

    return arrayOf
  },

  maybe (type) {
    function maybe (value, strict) {
      return nativeTypes.Null(value) || typeforce(type, value, strict)
    }
    maybe.toJSON = function () { return '?' + (type.toJSON && type.toJSON() || JSON.stringify(type)) }

    return maybe
  },

  object (type) {
    function object (value, strict) {
      typeforce(nativeTypes.Object, value, strict)

      var propertyName, propertyType, propertyValue

      try {
        for (propertyName in type) {
          propertyType = type[propertyName]
          propertyValue = value[propertyName]

          typeforce(propertyType, propertyValue, strict)
        }

      } catch (e) {
        throw new TypeError(tfPropertyErrorString(propertyType, propertyName, propertyValue))
      }

      if (strict) {
        for (propertyName in value) {
          if (type[propertyName]) continue

          throw new TypeError('Unexpected property "' + propertyName + '"')
        }
      }

      return true
    }
    object.toJSON = function () { return JSON.stringify(type) }

    return object
  },

  oneOf (types) {
    return function oneOf (value, strict) {
      return types.some(type => {
        try {
          return typeforce(type, value, strict)

        } catch (e) {
          return false
        }
      })
    }
  },

  compile (type) {
    if (nativeTypes.String(type)) {
      if (type[0] === '?') {
        type = type.slice(1)

        return otherTypes.maybe(otherTypes.compile(type))
      }

      var nativeType = nativeTypes[type]
      if (nativeType) return nativeType

    } else if (nativeTypes.Object(type)) {
      if (nativeTypes.Array(type)) {
        return otherTypes.arrayOf(otherTypes.compile(type[0]))
      }

      var compiled = {}

      for (var propertyName in type) {
        compiled[propertyName] = otherTypes.compile(type[propertyName])
      }

      return compiled
    }

    return type
  },

  value (expected) {
    return function value (actual) {
      return actual === expected
    }
  }
}

function typeforce (type, value, strict) {
  switch (typeof type) {
    case 'function':
      if (type(value, strict)) return true

      throw new TypeError(tfErrorString(getFunctionTypeName(type), value))

    case 'object':
      if (nativeTypes.Array(type)) return typeforce(otherTypes.arrayOf(type[0]), value, strict)

      return typeforce(otherTypes.object(type), value, strict)

    case 'string':
      if (type[0] === '?') {
        type = type.slice(1)

        return typeforce(otherTypes.maybe(type), value, strict)
      }

      var tfType = nativeTypes[type]
      if (tfType) return typeforce(tfType, value, strict)
      if (type === getTypeName(value)) return true

      break
  }

  // catch all
  throw new TypeError(tfErrorString(type, value))
}

// assign all types to typeforce function
var typeName
Object.keys(nativeTypes).forEach(typeName => {
  var nativeType = nativeTypes[typeName]
  nativeType.toJSON = () => typeName

  typeforce[typeName] = nativeType
})

for (typeName in otherTypes) {
  typeforce[typeName] = otherTypes[typeName]
}

module.exports = typeforce
<|endoftext|>


<commit_before>(function() {
	function SongPlayer() {
		var SongPlayer = {};

		var currentSong = null;
		/**
		* @desc Buzz object audio file
		* @type {Object}
		*/
		var currentBuzzObject = null;
		/**
		* @function setSong
		* @desc Stops currently playing song and load new audio file as currentBuzzObject
		* @param {Object} song
		**/

		var setSong = function(song) {
			if (currentBuzzObject) {
				currentBuzzObject.stop();
				currentSong.playing = null;
			}

			currentBuzzObject = new buzz.sound(song.audioUrl, {
				formats: ['mp3'],
				preload: true
			});

			currentSong = song;

		};
		/**
		* @function playSong
		* @desc plays currentBuzzObject and sets song.playing boolean to TRUE
		* @param {Object} song
		*/

		var playSong = function(song) {
			currentBuzzObject.play();
			song.playing = true;
		};

		}

		SongPlayer.play = function(song) {
			if (currentSong !== song) {
				setSong(song);
				playSong(song);
// check if current song matches clicked song, and if that song is paused. if paused, resume playing.
			} else if (currentSong === song) {
				if (currentBuzzObject.isPaused()) {
					currentBuzzObject.play();
// update song.playing boolean for reference in album.html

				}
			}
		};

		SongPlayer.pause = function(song) {
			currentBuzzObject.pause();
			song.playing = false;
		};

		return SongPlayer;

	angular
		.module('blocJams')
		.factory('SongPlayer', SongPlayer);
})();<commit_msg>checkpoint-8-working<commit_after>(function() {
	function SongPlayer(Fixtures) {
		var SongPlayer = {};

		var currentSong = null;
		/**
		* @desc Buzz object audio file
		* @type {Object}
		*/
		var currentBuzzObject = null;
		/**
		* @function setSong
		* @desc Stops currently playing song and load new audio file as currentBuzzObject
		* @param {Object} song
		**/

		var setSong = function(song) {
			if (currentBuzzObject) {
				currentBuzzObject.stop();
				currentSong.playing = null;
			}

			currentBuzzObject = new buzz.sound(song.audioUrl, {
				formats: ['mp3'],
				preload: true
			});

			currentSong = song;

		};
		/**
		* @function playSong
		* @desc plays currentBuzzObject and sets song.playing boolean to TRUE
		* @param {Object} song
		*/

		var playSong = function(song) {
			currentBuzzObject.play();
			song.playing = true;
		};

		}

		SongPlayer.play = function(song) {
			if (currentSong !== song) {
				setSong(song);
				playSong(song);
// check if current song matches clicked song, and if that song is paused. if paused, resume playing.
			} else if (currentSong === song) {
				if (currentBuzzObject.isPaused()) {
					currentBuzzObject.play();
// update song.playing boolean for reference in album.html

				}
			}
		};

		SongPlayer.pause = function(song) {
			currentBuzzObject.pause();
			song.playing = false;
		};

		return SongPlayer;

	angular
		.module('blocJams')
		.factory('SongPlayer', SongPlayer);
})();<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
<commit_msg>creating a cool scrolly thing<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

require('./styles/style.scss');

ReactDOM.render(<App />, document.getElementById('root'));
<|endoftext|>


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

package.service.netcontrol = function ServiceNetControl(me) {
    me.setup = function (callback, ref) {
        callback();
    };
    me.effects = {
        autoIncreasePacketDelay:true,
        packetDelay:0
    };
    me.signal = function() {
        if(me.effects.autoIncreasePacketDelay) {
            var packetDelay = parseInt(me.effects.packetDelay);
            if(!packetDelay || packetDelay < 0) {
                packetDelay = 0;
            }
            me.effects.packetDelay = packetDelay + 5;
            me.applyEffects(() => {

            }, me.effects);
        }
    };
    me.reset = function(callback) {
        me.effects = {autoIncreasePacketDelay:true};
        me.applyEffects(callback, me.effects);
    };
    me.retrieveEffects = function(callback) {
        callback(me.effects);
    };
    me.applyEffects = function(callback, effects) {
        var device = me.service.netmonitor.device;
        if(!device) {
            device = "wlan0";
        }
        if(!effects) {
            effects = {};
        }
        me.effects = effects;
        me.core.console.log("using device: "+ device + " to set effects: " + JSON.stringify(effects));
        var cmd = require('node-cmd');
        me.flow(callback, (flow) => {
            flow.check(cmd, "cannot retrieve command lib");
            flow.async(cmd.get, "pwd", flow.callback);
            flow.wait((err, data, stderr) => {
                flow.error(err, "failed to list current directory");
                flow.check(!stderr, "failed with stderr: " + stderr);
                me.core.console.log("list current directory: " + data);
                flow.async(cmd.get, "sudo tc qdisc del root dev " + device, flow.callback);
                flow.wait((err, data, stderr) => {
                    if(err) {
                        me.core.console.log(err.message);
                    }
                    me.core.console.log("reset device output: " + data);
                    if(effects.packetLoss || effects.packetDelay) {
                        me.core.console.log("setting packet loss to: " + effects.packetLoss);
                        me.core.console.log("setting packet delay to: " + effects.packetDelay);
                        if(effects.packetDelay) {
                            flow.async(cmd.get, "sudo tc qdisc add dev " + device + " root netem delay " + effects.packetDelay + "ms", flow.callback);
                        }
                        if(effects.packetLoss) {
                            flow.async(cmd.get, "sudo tc qdisc add dev " + device + " root netem loss " + effects.packetLoss + "%", flow.callback);
                        }
                        flow.wait((err, data, stderr) => {
                            flow.error(err, "failed to set command:" + device);
                            flow.check(!stderr, "failed with stderr: " + stderr);
                            me.core.console.log("set command output: " + data);
                        }, () => {
                            me.core.console.log("completed sending: " + JSON.stringify(effects) + " after sending: " + flow.waitCount + " commands");
                            flow.end();
                        });
                    }
                    else {
                        flow.end();
                    }
                });
            });
        });
    };
};
<commit_msg>support for max packet delay increase<commit_after>/*
 @author Zakai Hamilton
 @component ServiceNetControl
 */

package.service.netcontrol = function ServiceNetControl(me) {
    me.setup = function (callback, ref) {
        callback();
    };
    me.defaultEffects = {
        autoIncreasePacketDelay:true,
        packetDelay:0,
        packetDelayIncrease:5,
        packetDelayMax:300
    };
    me.effects = Object.assign({}, me.defaultEffects);
    me.signal = function() {
        if(me.effects.autoIncreasePacketDelay) {
            var packetDelay = parseInt(me.effects.packetDelay);
            if(!packetDelay || packetDelay < 0) {
                packetDelay = 0;
            }
            me.effects.packetDelay = packetDelay + me.effects.packetDelayIncrease;
            if(me.effects.packetDelay > me.effects.packetDelayMax) {
                me.effects.packetDelay = 0;
            }
            me.applyEffects(() => {

            }, me.effects);
        }
    };
    me.reset = function(callback) {
        me.effects = Object.assign({}, me.defaultEffects);
        me.applyEffects(callback, me.effects);
    };
    me.retrieveEffects = function(callback) {
        callback(me.effects);
    };
    me.applyEffects = function(callback, effects) {
        var device = me.service.netmonitor.device;
        if(!device) {
            device = "wlan0";
        }
        if(!effects) {
            effects = {};
        }
        me.effects = effects;
        me.core.console.log("using device: "+ device + " to set effects: " + JSON.stringify(effects));
        var cmd = require('node-cmd');
        me.flow(callback, (flow) => {
            flow.check(cmd, "cannot retrieve command lib");
            flow.async(cmd.get, "pwd", flow.callback);
            flow.wait((err, data, stderr) => {
                flow.error(err, "failed to list current directory");
                flow.check(!stderr, "failed with stderr: " + stderr);
                me.core.console.log("list current directory: " + data);
                flow.async(cmd.get, "sudo tc qdisc del root dev " + device, flow.callback);
                flow.wait((err, data, stderr) => {
                    if(err) {
                        me.core.console.log(err.message);
                    }
                    me.core.console.log("reset device output: " + data);
                    if(effects.packetLoss || effects.packetDelay) {
                        me.core.console.log("setting packet loss to: " + effects.packetLoss);
                        me.core.console.log("setting packet delay to: " + effects.packetDelay);
                        if(effects.packetDelay) {
                            flow.async(cmd.get, "sudo tc qdisc add dev " + device + " root netem delay " + effects.packetDelay + "ms", flow.callback);
                        }
                        if(effects.packetLoss) {
                            flow.async(cmd.get, "sudo tc qdisc add dev " + device + " root netem loss " + effects.packetLoss + "%", flow.callback);
                        }
                        flow.wait((err, data, stderr) => {
                            flow.error(err, "failed to set command:" + device);
                            flow.check(!stderr, "failed with stderr: " + stderr);
                            me.core.console.log("set command output: " + data);
                        }, () => {
                            me.core.console.log("completed sending: " + JSON.stringify(effects) + " after sending: " + flow.waitCount + " commands");
                            flow.end();
                        });
                    }
                    else {
                        flow.end();
                    }
                });
            });
        });
    };
};
<|endoftext|>


<commit_before> (function () {
     function SongPlayer() {
         var SongPlayer = {};
         var currentSong = null;
         /**
          * @desc Buzz object audio file
          * @type {Object}
          */
         var currentBuzzObject = null;
         /**
          * @function setSong
          * @desc Stops currently playing song and loads new audio file as currentBuzzObject
          * @param {Object} song
          */
         var setSong = function (song) {
             if (currentBuzzObject) {
                 currentBuzzObject.stop();
                 currentSong.playing = null;
             }

             currentBuzzObject = new buzz.sound(song.audioUrl, {
                 formats: ['mp3'],
                 preload: true
             });

             currentSong = song;
         };

         SongPlayer.play = function (song) {
             if (currentSong !== song) {
                 setSong(song);
                 currentBuzzObject.play();
                 song.playing = true;
             } else if (currentSong === song) {
                 if (currentBuzzObject.isPaused()) {
                     currentBuzzObject.play();
                     song.playing = true;
                 }
             }
         };

         SongPlayer.pause = function (song) {
             currentBuzzObject.pause();
             song.playing = false;
         };

         return SongPlayer;
     }

     angular
         .module('blocJams')
         .factory('SongPlayer', SongPlayer);
 })();
<commit_msg>211601AUG2017<commit_after> (function () {
     /**
          * @function SongPlayer
          * @desc Major player functions
          * @returns {Object} Object that implemetns basic play/pause functionality
          */
     function SongPlayer() {
         /**
          * @desc object of the simple media operations
          * @type {Object}
          */
         var SongPlayer = {};
         /**
          * @desc flag of the song state
          * @type {boolean}
          */
         var currentSong = null;
         /**
          * @desc Buzz object audio file
          * @type {Object}
          */
         var currentBuzzObject = null;
         /**
          * @function setSong
          * @desc Stops currently playing song and loads new audio file as currentBuzzObject
          * @param {Object} song
          */
         var setSong = function (song) {
             if (currentBuzzObject) {
                 currentBuzzObject.stop();
                 currentSong.playing = null;
             }

             currentBuzzObject = new buzz.sound(song.audioUrl, {
                 formats: ['mp3'],
                 preload: true
             });

             currentSong = song;
         };
         /**
          * @function playSong
          * @desc plays currentBuzzObject and changes currentSong.playting to true
          */
         var playSong = function () {
             currentBuzzObject.play();
             currentSong.playing = true;
         };

         /**
          * @ngdoc function
          * @name SongpPlayer.play
          * @description This method playing the song
          * @param {Object} song
          */
         SongPlayer.play = function (song) {
             if (currentSong !== song) {
                 setSong(song);
                 playSong();
             } else if (currentSong === song) {
                 if (currentBuzzObject.isPaused()) {
                     playSong();
                 }
             }
         };
         /**
          * @ngdoc function
          * @name SongpPlayer.pause
          * @description This method pausing the song
          * @param {Object} song
          */
         SongPlayer.pause = function (song) {
             currentBuzzObject.pause();
             song.playing = false;
         };

         return SongPlayer;
     }

     angular
         .module('blocJams')
         .factory('SongPlayer', SongPlayer);
 })();
<|endoftext|>


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

/**
Command-line interface (CLI) for HackMyResume.
@license MIT. Copyright (c) 2015 hacksalot (https://github.com/hacksalot)
@module index.js
*/

var SPAWNW = require('./core/spawn-watch')
  , FCMD  = require( './hackmycmd')
  , PKG = require('../package.json')
  , FS = require('fs')
  , chalk = require('chalk')
  , PATH = require('path')
  , HACKMYSTATUS = require('./core/status-codes')
  , opts = { }
  , title = chalk.white.bold('\n*** HackMyResume v' + PKG.version + ' ***')
  , StringUtils = require('./utils/string.js')
  , _ = require('underscore')
  , Command = require('commander').Command;

try {
  main();
}
catch( ex ) {
  require('./core/error-handler').err( ex, true );
}

/**
Kick off the HackMyResume application.
*/
function main() {

  var args = initialize();

  function execCommand() {
    var argsArray = Array.prototype.slice.call(arguments);
    //console.log(argsArray);
    return FCMD.verbs[ this.name() ].apply( null, argsArray );
  }

  // Create the top-level (application) command...
  var program = new Command('hackmyresume')
    .version(PKG.version)
    .description(chalk.yellow.bold('*** HackMyResume ***'))
    .option('-s, --silent', 'Run in silent mode.')
    .usage('COMMAND <sources> [TO <targets>]');

  // Create the NEW command
  program
    .command('new')
    .arguments('<sources...>')
    .option('-f --format <fmt>', 'FRESH or JRS format', 'FRESH')
    .alias('create')
    .description('Create resume(s) in FRESH or JSON RESUME format.')
    .action(function( sources ) {
      execCommand.call( this, sources, [], this.opts(), logMsg );
    });

  // Create the VALIDATE command
  program
    .command('validate')
    .arguments('<sources...>')
    .description('Validate a resume in FRESH or JSON RESUME format.')
    .action(function(sources) {
      execCommand.call(this, sources, [], this.opts(), logMsg);
    });

  // Create the CONVERT command
  program
    .command('convert')
    //.arguments('<sources...>')
    .description('Convert a resume to/from FRESH or JSON RESUME format.')
    .action(function() {
      var x = splitSrcDest.call( this );
      execCommand.call( this, x.src, x.dst, this.opts(), logMsg );
    });

  // Create the ANALYZE command
  program
    .command('analyze')
    .arguments('<sources...>')
    .description('Analyze one or more resumes.')
    .action(function() {
      execCommand.call(this, sources, [], this.opts(), logMsg);
    });

  // Create the BUILD command
  program
    .command('build')
    .alias('generate')
    //.arguments('<sources> TO [targets]')
    //.usage('...')
    .option('-t --theme <theme>', 'Theme name or path')
    .option('-p --prettify', 'Preffity HTML output.')
    .description('Generate resume to multiple formats')
    .action(function( sources, targets, options ) {
      var x = splitSrcDest.call( this );
      execCommand.call( this, x.src, x.dst, opts, logMsg );
    });

  // program.on('--help', function(){
  //   console.log('  Examples:');
  //   console.log('');
  //   console.log('    $ custom-help --help');
  //   console.log('    $ custom-help -h');
  //   console.log('');
  // });

  program.parse( args );

  if (!program.args.length) { throw { fluenterror: 4 }; }

}

/**
Split multiple command-line filenames by the 'TO' keyword
*/
function splitSrcDest() {

  var params = this.parent.args.filter(function(j) { return String.is(j); });
  if( params.length === 0 )
    throw { fluenterror: HACKMYSTATUS.resumeNotFound };

  // Find the TO keyword, if any
  var splitAt = _.findIndex( params, function(p) {
    return p.toLowerCase() === 'to';
  });

  // TO can't be the last keyword
  if( splitAt === params.length - 1 && splitAt !== -1 ) {
    logMsg(chalk.yellow('Please ') +
      chalk.yellow.bold('specify an output file') +
      chalk.yellow(' for this operation or ') +
      chalk.yellow.bold('omit the TO keyword') +
      chalk.yellow('.') );
    return;
  }

  return {
    src: params.slice(0, splitAt === -1 ? undefined : splitAt ),
    dst: splitAt === -1 ? [] : params.slice( splitAt + 1 )
  };
}

/**
Massage command-line args and setup Commander.js.
*/
function initialize() {

  // Support case-insensitive sub-commands (build, generate, validate, etc.)..
  var oVerb, verb = '', args = process.argv.slice(), cleanArgs = args.slice(2);
  if( cleanArgs.length ) {
    var verbIdx = _.findIndex( cleanArgs, function(v){ return v[0] !== '-'; });
    if( verbIdx !== -1 ) {
      oVerb = cleanArgs[ verbIdx ];
      verb = args[ verbIdx + 2 ] = oVerb.trim().toLowerCase();
    }
  }

  // Handle invalid verbs here (a bit easier here than in commander.js)...
  if( !FCMD.verbs[ verb ] && !FCMD.alias[ verb ] ) {
    throw { fluenterror: HACKMYSTATUS.invalidCommand, shouldExit: true,
            attempted: oVerb };
  }

  // Override the .missingArgument behavior
  Command.prototype.missingArgument = function(name) {
    throw { fluenterror: HACKMYSTATUS.resumeNotFound };
  };

  // Override the .helpInformation behavior
  Command.prototype.helpInformation = function() {
    var manPage = FS.readFileSync( PATH.join(__dirname, 'use.txt'), 'utf8' );
    return chalk.green.bold(manPage);
  };

  return args;
}

/**
Simple logging placeholder.
*/
function logMsg( msg ) {
  opts.silent || console.log( msg );
}

/**
Fetch options from command line arguments.
*/
function getOpts( args ) {
  var noPretty = args.nopretty || args.n;
  noPretty = noPretty && (noPretty === true || noPretty === 'true');
  return {
    theme: args.t || 'modern',
    format: args.f || 'FRESH',
    prettify: !noPretty,
    silent: args.s || args.silent,
    css: args.css || 'embed',
    help: args.help || undefined
  };
}
<commit_msg>Remove unnecessary indirection.<commit_after>#! /usr/bin/env node

/**
Command-line interface (CLI) for HackMyResume.
@license MIT. Copyright (c) 2015 hacksalot (https://github.com/hacksalot)
@module index.js
*/

var SPAWNW = require('./core/spawn-watch')
  , FCMD  = require( './hackmycmd')
  , PKG = require('../package.json')
  , FS = require('fs')
  , chalk = require('chalk')
  , PATH = require('path')
  , HACKMYSTATUS = require('./core/status-codes')
  , opts = { }
  , title = chalk.white.bold('\n*** HackMyResume v' + PKG.version + ' ***')
  , StringUtils = require('./utils/string.js')
  , _ = require('underscore')
  , Command = require('commander').Command;

try {
  main();
}
catch( ex ) {
  require('./core/error-handler').err( ex, true );
}

/**
Kick off the HackMyResume application.
*/
function main() {

  var args = initialize();

  // Create the top-level (application) command...
  var program = new Command('hackmyresume')
    .version(PKG.version)
    .description(chalk.yellow.bold('*** HackMyResume ***'))
    .option('-s, --silent', 'Run in silent mode.')
    .usage('COMMAND <sources> [TO <targets>]');

  // Create the NEW command
  program
    .command('new')
    .arguments('<sources...>')
    .option('-f --format <fmt>', 'FRESH or JRS format', 'FRESH')
    .alias('create')
    .description('Create resume(s) in FRESH or JSON RESUME format.')
    .action(function( sources ) {
      FCMD.verbs[ this.name() ].call( null, sources, [], this.opts(), logMsg);
    });

  // Create the VALIDATE command
  program
    .command('validate')
    .arguments('<sources...>')
    .description('Validate a resume in FRESH or JSON RESUME format.')
    .action(function(sources) {
      FCMD.verbs[ this.name() ].call( null, sources, [], this.opts(), logMsg);
    });

  // Create the CONVERT command
  program
    .command('convert')
    //.arguments('<sources...>')
    .description('Convert a resume to/from FRESH or JSON RESUME format.')
    .action(function() {
      var x = splitSrcDest.call( this );
      FCMD.verbs[ this.name() ].call( null, x.src, x.dst, this.opts(), logMsg);
    });

  // Create the ANALYZE command
  program
    .command('analyze')
    .arguments('<sources...>')
    .description('Analyze one or more resumes.')
    .action(function( sources ) {
      FCMD.verbs[ this.name() ].call( null, sources, [], this.opts(), logMsg);
    });

  // Create the BUILD command
  program
    .command('build')
    .alias('generate')
    //.arguments('<sources> TO [targets]')
    //.usage('...')
    .option('-t --theme <theme>', 'Theme name or path')
    .option('-p --prettify', 'Preffity HTML output.')
    .description('Generate resume to multiple formats')
    .action(function( sources, targets, options ) {
      var x = splitSrcDest.call( this );
      FCMD.verbs[ this.name() ].call( null, x.src, x.dst, this.opts(), logMsg);
    });

  // program.on('--help', function(){
  //   console.log('  Examples:');
  //   console.log('');
  //   console.log('    $ custom-help --help');
  //   console.log('    $ custom-help -h');
  //   console.log('');
  // });

  program.parse( args );

  if (!program.args.length) { throw { fluenterror: 4 }; }

}

/**
Split multiple command-line filenames by the 'TO' keyword
*/
function splitSrcDest() {

  var params = this.parent.args.filter(function(j) { return String.is(j); });
  if( params.length === 0 )
    throw { fluenterror: HACKMYSTATUS.resumeNotFound };

  // Find the TO keyword, if any
  var splitAt = _.findIndex( params, function(p) {
    return p.toLowerCase() === 'to';
  });

  // TO can't be the last keyword
  if( splitAt === params.length - 1 && splitAt !== -1 ) {
    logMsg(chalk.yellow('Please ') +
      chalk.yellow.bold('specify an output file') +
      chalk.yellow(' for this operation or ') +
      chalk.yellow.bold('omit the TO keyword') +
      chalk.yellow('.') );
    return;
  }

  return {
    src: params.slice(0, splitAt === -1 ? undefined : splitAt ),
    dst: splitAt === -1 ? [] : params.slice( splitAt + 1 )
  };
}

/**
Massage command-line args and setup Commander.js.
*/
function initialize() {

  // Support case-insensitive sub-commands (build, generate, validate, etc.)..
  var oVerb, verb = '', args = process.argv.slice(), cleanArgs = args.slice(2);
  if( cleanArgs.length ) {
    var verbIdx = _.findIndex( cleanArgs, function(v){ return v[0] !== '-'; });
    if( verbIdx !== -1 ) {
      oVerb = cleanArgs[ verbIdx ];
      verb = args[ verbIdx + 2 ] = oVerb.trim().toLowerCase();
    }
  }

  // Handle invalid verbs here (a bit easier here than in commander.js)...
  if( verb && !FCMD.verbs[ verb ] && !FCMD.alias[ verb ] ) {
    throw { fluenterror: HACKMYSTATUS.invalidCommand, shouldExit: true,
            attempted: oVerb };
  }

  // Override the .missingArgument behavior
  Command.prototype.missingArgument = function(name) {
    throw { fluenterror: HACKMYSTATUS.resumeNotFound };
  };

  // Override the .helpInformation behavior
  Command.prototype.helpInformation = function() {
    var manPage = FS.readFileSync( PATH.join(__dirname, 'use.txt'), 'utf8' );
    return chalk.green.bold(manPage);
  };

  return args;
}

/**
Simple logging placeholder.
*/
function logMsg( msg ) {
  opts.silent || console.log( msg );
}

/**
Fetch options from command line arguments.
*/
function getOpts( args ) {
  var noPretty = args.nopretty || args.n;
  noPretty = noPretty && (noPretty === true || noPretty === 'true');
  return {
    theme: args.t || 'modern',
    format: args.f || 'FRESH',
    prettify: !noPretty,
    silent: args.s || args.silent,
    css: args.css || 'embed',
    help: args.help || undefined
  };
}
<|endoftext|>


<commit_before>// General-purpose utilities.

const assign = Object.assign;
const freeze = Object.freeze;
const keys = Object.keys;

const mapValues = (obj, func) => keys(obj).reduce((o, key) => {
    o[key] = func(obj[key], key);
    return o;
}, {});

// Type detection utilities.

const isFunction = value => typeof value === "function";

const isAsyncAction = value => value && isFunction(value._asyncAction);

// Async actions.

/**
 * Creates an async action from the given function.
 *
 * The function must be of type ({getState, resolve, dispatch}) => action.
 *
 * This needs to be used in conjunction with asyncActionMiddleware.
 */
export const createAsyncAction = func => ({_asyncAction: func});

// Stores.

const createUnsubscribe = (listeners, listener) => () => {
    const index = listeners.indexOf(listener);
    if (index != -1) {
        listeners.splice(index, 1);
    }
};

const defaultResolve = store => next => action => next(action);

/**
 * Creates a wrapped state object and returns two functions for
 * interacting with it.
 *
 * getState(): Returns a snapshot of the current state.
 * subscribe(listener): Will notify the listener on any change to the state,
 *     and immediately call the listener to notify of current state. Returns
 *     an unsubscribe function.
 * dispatch(action): Mutates the state using the given action. An action is a
 *     function that is called with the current state, and returns the new
 *     state.
 */
export const createStore = () => {
    let debounced = 0;
    // Wrapped state.
    let state;
    const getState = () => state;
    // Subscriptions management.
    const listeners = [];
    const subscribe = listener => {
        listeners.push(listener);
        listener(state);
        // The unsubscribe function.
        return createUnsubscribe(listeners, listener);
    };
    const notify = (initialState, newState) => {
        // Only update the listeners if we've finished debouncing and the state has actually changed.
        if (newState !== initialState && debounced === 0) {
            listeners.forEach(listener => listener(state));
        }
    };
    // State management.
    const dispatch = action => {
        if (!isFunction(action)) {
            throw new Error(`Actions should be plain functions: ${action}`);
        }
        const initialState = state;
        state = action(state);
        notify(initialState, state);
    };
    // Debounced dispatch.
    const debounce = func => (...args) => {
        const initialState = state;
        debounced += 1;
        try {
            return func(...args);
        } finally {
            debounced -= 1;
            notify(initialState, state);
        }
    };
    // All done!
    return {getState, subscribe, resolve: defaultResolve, dispatch, debounce};
};

// Middleware.

/**
 * Middleware used to process actions created by
 * createAsyncAction().
 */
export const asyncActionMiddleware = ({getState, dispatch, debounce}) => next => action => isAsyncAction(action) ? debounce(action._asyncAction)(dispatch, getState) : next(action);

const enhanceStore = ({getState, resolve, dispatch: baseDispatch, debounce, ...store}) => {
    const dispatch = resolve({getState, resolve, dispatch: action => dispatch(action), debounce})(baseDispatch);
    return {getState, resolve, dispatch, debounce, ...store};
};

const reduceMiddleware = middlewareList => store => {
    const boundMiddlewareList = middlewareList.map(m => m(store));
    return next => boundMiddlewareList.reduceRight((m2, m1) => m1(m2), next);
};

/**
 * Store enhancer that applies the given middleware.
 */
export const applyMiddleware = (...middlewareList) => createStore => (...args) => {
    const {resolve: baseResolve, ...store} = createStore(...args);
    const resolve = reduceMiddleware([...middlewareList, baseResolve]);
    return enhanceStore({resolve, ...store});
};

// Action creators.

/**
 * An action creator that will merge the existing
 * state with the new state.
 *
 * If any of the keys of the new state are actions,
 * then they will be called with the previous value
 * of the state at that key to mutate the existing
 * value.
 */
export const setState = obj => (state={}) => freeze(assign({}, state, mapValues(obj, (value, key) => isFunction(value) ? value(state[key]) : value)));

const bindActionCreator = (actionCreator, dispatch) => (...args) => {
    const action = actionCreator(...args);
    dispatch(action);
    return action;
};

const createNestedGetState = (getState, key) => () => (getState() || {})[key];

const createNestedDispatch = (dispatch, key) => action => dispatch(setState({[key]: action}));

const bindActionCreators = (actionCreators, {getState, dispatch, ...store}) => {
    // Bind objects of action creators.
    const actions = mapValues(actionCreators, (actionCreator, key) => {
        // Bind action creators.
        if (isFunction(actionCreator)) {
            return bindActionCreator(actionCreator, dispatch);
        }
        // Bind nested actions.
        return bindActionCreators(actionCreator, enhanceStore({
            getState: createNestedGetState(getState, key),
            dispatch: createNestedDispatch(dispatch, key),
            ...store
        }));
    });
    // Run the default action.
    const {initialize} = actions;
    if (isFunction(initialize)) {
        initialize();
    }
    // All done!
    return actions;
};

/**
 * Store enhancer that recursively binds an object of action creators to the
 * given store.
 *
 * If the object of action creators contains a "initialize"
 * key, then that action creator will be called automatically
 * to set initial state.
 *
 * The returned store will have an "actions" property.
 */
export const applyActionCreators = actionCreators => createStore => (...args) => {
    const store = createStore(...args);
    const actions = bindActionCreators(actionCreators, store);
    return {actions, ...store};
};
<commit_msg>Updating docstring for store<commit_after>// General-purpose utilities.

const assign = Object.assign;
const freeze = Object.freeze;
const keys = Object.keys;

const mapValues = (obj, func) => keys(obj).reduce((o, key) => {
    o[key] = func(obj[key], key);
    return o;
}, {});

// Type detection utilities.

const isFunction = value => typeof value === "function";

const isAsyncAction = value => value && isFunction(value._asyncAction);

// Async actions.

/**
 * Creates an async action from the given function.
 *
 * The function must be of type ({getState, resolve, dispatch}) => action.
 *
 * This needs to be used in conjunction with asyncActionMiddleware.
 */
export const createAsyncAction = func => ({_asyncAction: func});

// Stores.

const createUnsubscribe = (listeners, listener) => () => {
    const index = listeners.indexOf(listener);
    if (index != -1) {
        listeners.splice(index, 1);
    }
};

const defaultResolve = store => next => action => next(action);

/**
 * Creates a wrapped state object and returns two functions for
 * interacting with it.
 *
 * getState(): Returns a snapshot of the current state.
 * subscribe(listener): Will notify the listener on any change to the state,
 *     and immediately call the listener to notify of current state. Returns
 *     an unsubscribe function.
 * resolve(store)(next)(action): A middleware function representing the entire
 *     middleware chain being used by the store. Use this to chain further
 *     middleware, or resolve nested actions.
 * dispatch(action): Mutates the state using the given action. An action is a
 *     function that is called with the current state, and returns the new
 *     state.
 * debounce(func): Wraps the given function so that, for the duration of it's
 *     call, any number of synchronous calls to dispatch will only result in
 *     a single notification sent to subscribers.
 */
export const createStore = () => {
    let debounced = 0;
    // Wrapped state.
    let state;
    const getState = () => state;
    // Subscriptions management.
    const listeners = [];
    const subscribe = listener => {
        listeners.push(listener);
        listener(state);
        // The unsubscribe function.
        return createUnsubscribe(listeners, listener);
    };
    const notify = (initialState, newState) => {
        // Only update the listeners if we've finished debouncing and the state has actually changed.
        if (newState !== initialState && debounced === 0) {
            listeners.forEach(listener => listener(state));
        }
    };
    // State management.
    const dispatch = action => {
        if (!isFunction(action)) {
            throw new Error(`Actions should be plain functions: ${action}`);
        }
        const initialState = state;
        state = action(state);
        notify(initialState, state);
    };
    // Debounced dispatch.
    const debounce = func => (...args) => {
        const initialState = state;
        debounced += 1;
        try {
            return func(...args);
        } finally {
            debounced -= 1;
            notify(initialState, state);
        }
    };
    // All done!
    return {getState, subscribe, resolve: defaultResolve, dispatch, debounce};
};

// Middleware.

/**
 * Middleware used to process actions created by
 * createAsyncAction().
 */
export const asyncActionMiddleware = ({getState, dispatch, debounce}) => next => action => isAsyncAction(action) ? debounce(action._asyncAction)(dispatch, getState) : next(action);

const enhanceStore = ({getState, resolve, dispatch: baseDispatch, debounce, ...store}) => {
    const dispatch = resolve({getState, resolve, dispatch: action => dispatch(action), debounce})(baseDispatch);
    return {getState, resolve, dispatch, debounce, ...store};
};

const reduceMiddleware = middlewareList => store => {
    const boundMiddlewareList = middlewareList.map(m => m(store));
    return next => boundMiddlewareList.reduceRight((m2, m1) => m1(m2), next);
};

/**
 * Store enhancer that applies the given middleware.
 */
export const applyMiddleware = (...middlewareList) => createStore => (...args) => {
    const {resolve: baseResolve, ...store} = createStore(...args);
    const resolve = reduceMiddleware([...middlewareList, baseResolve]);
    return enhanceStore({resolve, ...store});
};

// Action creators.

/**
 * An action creator that will merge the existing
 * state with the new state.
 *
 * If any of the keys of the new state are actions,
 * then they will be called with the previous value
 * of the state at that key to mutate the existing
 * value.
 */
export const setState = obj => (state={}) => freeze(assign({}, state, mapValues(obj, (value, key) => isFunction(value) ? value(state[key]) : value)));

const bindActionCreator = (actionCreator, dispatch) => (...args) => {
    const action = actionCreator(...args);
    dispatch(action);
    return action;
};

const createNestedGetState = (getState, key) => () => (getState() || {})[key];

const createNestedDispatch = (dispatch, key) => action => dispatch(setState({[key]: action}));

const bindActionCreators = (actionCreators, {getState, dispatch, ...store}) => {
    // Bind objects of action creators.
    const actions = mapValues(actionCreators, (actionCreator, key) => {
        // Bind action creators.
        if (isFunction(actionCreator)) {
            return bindActionCreator(actionCreator, dispatch);
        }
        // Bind nested actions.
        return bindActionCreators(actionCreator, enhanceStore({
            getState: createNestedGetState(getState, key),
            dispatch: createNestedDispatch(dispatch, key),
            ...store
        }));
    });
    // Run the default action.
    const {initialize} = actions;
    if (isFunction(initialize)) {
        initialize();
    }
    // All done!
    return actions;
};

/**
 * Store enhancer that recursively binds an object of action creators to the
 * given store.
 *
 * If the object of action creators contains a "initialize"
 * key, then that action creator will be called automatically
 * to set initial state.
 *
 * The returned store will have an "actions" property.
 */
export const applyActionCreators = actionCreators => createStore => (...args) => {
    const store = createStore(...args);
    const actions = bindActionCreators(actionCreators, store);
    return {actions, ...store};
};
<|endoftext|>