<commit_before>// This is main process of Electron, started as first thing when your
// app starts. This script is running through entire life of your application.
// It doesn't have any windows which you can see on screen, but we can open
// window from here.

// This process cannot access the same resources in app.js.
// The proper way to do IPC is through ipcMain and ipcRender.
// This process is `ipcMain`.

import {os} from 'os';
import {app, Menu, ipcMain, autoUpdater} from 'electron';
import {devMenuTemplate} from './menu/dev_menu_template';
import {editMenuTemplate} from './menu/edit_menu_template';
import createWindow from './helpers/window';
import populateClasses from './warm_up';
import cache from './simple_cache';
import { config } from './simple_config';

// Special module holding environment variables which you declared
// in config/env_xxx.json file.
import env from './env';
import createServer from './editor_api';

let preferences = config.get('preferences');
app.commandLine.appendSwitch('--disable-http-cache');

// const os = require('os');

const setApplicationMenu = function setApplicationMenu() {
  const menus = [editMenuTemplate];

  if (env.name !== 'production') {
    menus.push(devMenuTemplate);
  }

  Menu.setApplicationMenu(Menu.buildFromTemplate(menus));
};

function isIncognitoClass(className) {
  // / Skip incognito classes
  if (preferences === undefined || preferences.incognito === undefined) {
    return false;
  }

  const incognitoRules = preferences.incognito;
  for (const rule of incognitoRules) {
    if (className === rule) {
      return true;
    }

    if (className.search(rule) !== -1) {
      return true;
    }
  }

  return false;
}

function configAutoUpdater(updater, content) {
  const platform = `${os.platform()}_${os.arch()}`;
  const version = app.getVersion();

  updater.setFeedURL(`https://aicodes-nuts.herokuapp.com/update/${platform}/${version}`);
  updater.checkForUpdates();
  updater.on('update-downloaded',
    (event, releaseNotes, releaseName, releaseDate, updateURL) => {
      content.send('app-update-downloaded', releaseName);
    }
  );
  updater.on('checking-for-update', () => {
    console.log('Checking for updates');
  });
  updater.on('update-available', () => {
    console.log('Updates available');
  });
}

// Save userData in separate folders for each environment.
// Thanks to this you can use production and development versions of the app
// on same machine like those are two separate apps.
//
// TODO: This trick would work if we have a way to unify the settings path used by
// both app (render process) and remote (main process).
/*
if (env.name !== 'production') {
  const userDataPath = app.getPath('userData');
  app.setPath('userData', `${userDataPath} (${env.name})`);
  // remoteApp.setPath('userData', `${userDataPath} (${env.name})`);
}*/

/* OAuth protocol is not really a desktop-friendly protocol for
 * widely distributed desktop app. It is especially so for open source
 * desktop apps, as you'd need to store client key and secret somewhere.
 * Obfuscation creates fake sense of security anyway.
 *
 * We opt to do OAuth 100% server-side. We need a way to pass the
 * authenticated user token to Electron, though. The IPC mechanism
 * for WebContent (especially for non-electron page hosted online) is
 * rather limited. The `AIcodes hack` we came up is to monitor URL changes,
 * and backend would issue a special redirection, appending user token
 * to the redirect URL so Electron can capture.
 *
 * HTTPS protocol ensures that the URL is as secure as the page content.
 */
/*
function captureUserToken(window, content) {
  // Issue an async request. Will be captured by the event above.
   content.on('did-navigate', (event, url) => {
   content.on('found-in-page', (foundEvent, result) => {
   console.log('... found in page event is triggered....');
   console.log(result);
   content.stopFindInPage('clearSelection');
   // window.loadURL(`file://${__dirname}/app.html`);
   });
   content.findInPage('nuts');
   });
  content.on('did-finish-load', () => {
    console.log('finished loading');
     content.on('found-in-page', (foundEvent, result) => {
     console.log('... found in page event is triggered....');
     console.log(result);
     content.stopFindInPage('clearSelection');
     // window.loadURL(`file://${__dirname}/app.html`);
     });
     content.findInPage('demo.*ze');
  });

  content.on('did-navigate', (event, url) => {
    const results = url.split('#');
    if (results.length > 1) {
      console.log(`User Access Token is: ${results[1]}.`);
    }
  });
}
*/

app.on('ready', () => {
  setApplicationMenu();

  const mainWindow = createWindow('main', {
    width: 500,
    height: 800,
  });

  mainWindow.loadURL(`file://${__dirname}/app.html`);
  // mainWindow.loadURL('https://www.ai.codes/oauth.html');
  const content = mainWindow.webContents;
  // captureUserToken(mainWindow, content);

  /*
   if (env.name === 'development') {
   mainWindow.openDevTools();
   } */

  // ==== Starts a local Ai.codes server ========
  // Pre-populating a bunch of frequently used classes.
  content.on('did-finish-load', () => {
    populateClasses(content);
  });

  const PORT = 26337;
  const expressServer = createServer(content, cache, isIncognitoClass);

  expressServer.listen(PORT, () => {
    // Callback triggered when server is successfully listening. Hurray!
    console.log('Server listening on: http://localhost:%s', PORT);
  });

  // Skip checking version update if it is not production.
  if (env.name === 'production') {
    configAutoUpdater(autoUpdater, content);
  }

  ipcMain.on('update-quit-install', () => {
    mainWindow.setClosable(true);
    autoUpdater.quitAndInstall();
  });

  // ====== ai.codes code ends =========
});

app.on('window-all-closed', () => {
  app.quit();
});

app.on('will-quit', () => {
  app.quit();
});

// Store the class -> extension (JSON object) mapping to cache.
ipcMain.on('ice-cache', (event, className, extension) => {
  cache.set(className, extension);
});

// Preferences
ipcMain.on('load-preference', (event) => {
  const result = config.get('preferences');
  if (result === undefined) {
    config.set('preferences', {incognito: []});
  }

  event.sender.send('update-preference-display', config.get('preferences'));
});

ipcMain.on('save-preference', (event, updatedPreferences) => {
  preferences = updatedPreferences;
  config.set('preferences', updatedPreferences);
});

<commit_msg>get os back<commit_after>// This is main process of Electron, started as first thing when your
// app starts. This script is running through entire life of your application.
// It doesn't have any windows which you can see on screen, but we can open
// window from here.

// This process cannot access the same resources in app.js.
// The proper way to do IPC is through ipcMain and ipcRender.
// This process is `ipcMain`.

import {os} from 'os';
import {app, Menu, ipcMain, autoUpdater} from 'electron';
import {devMenuTemplate} from './menu/dev_menu_template';
import {editMenuTemplate} from './menu/edit_menu_template';
import createWindow from './helpers/window';
import populateClasses from './warm_up';
import cache from './simple_cache';
import { config } from './simple_config';

// Special module holding environment variables which you declared
// in config/env_xxx.json file.
import env from './env';
import createServer from './editor_api';

let preferences = config.get('preferences');
app.commandLine.appendSwitch('--disable-http-cache');

const os = require('os');

const setApplicationMenu = function setApplicationMenu() {
  const menus = [editMenuTemplate];

  if (env.name !== 'production') {
    menus.push(devMenuTemplate);
  }

  Menu.setApplicationMenu(Menu.buildFromTemplate(menus));
};

function isIncognitoClass(className) {
  // / Skip incognito classes
  if (preferences === undefined || preferences.incognito === undefined) {
    return false;
  }

  const incognitoRules = preferences.incognito;
  for (const rule of incognitoRules) {
    if (className === rule) {
      return true;
    }

    if (className.search(rule) !== -1) {
      return true;
    }
  }

  return false;
}

function configAutoUpdater(updater, content) {
  const platform = `${os.platform()}_${os.arch()}`;
  const version = app.getVersion();

  updater.setFeedURL(`https://aicodes-nuts.herokuapp.com/update/${platform}/${version}`);
  updater.checkForUpdates();
  updater.on('update-downloaded',
    (event, releaseNotes, releaseName, releaseDate, updateURL) => {
      content.send('app-update-downloaded', releaseName);
    }
  );
  updater.on('checking-for-update', () => {
    console.log('Checking for updates');
  });
  updater.on('update-available', () => {
    console.log('Updates available');
  });
}

// Save userData in separate folders for each environment.
// Thanks to this you can use production and development versions of the app
// on same machine like those are two separate apps.
//
// TODO: This trick would work if we have a way to unify the settings path used by
// both app (render process) and remote (main process).
/*
if (env.name !== 'production') {
  const userDataPath = app.getPath('userData');
  app.setPath('userData', `${userDataPath} (${env.name})`);
  // remoteApp.setPath('userData', `${userDataPath} (${env.name})`);
}*/

/* OAuth protocol is not really a desktop-friendly protocol for
 * widely distributed desktop app. It is especially so for open source
 * desktop apps, as you'd need to store client key and secret somewhere.
 * Obfuscation creates fake sense of security anyway.
 *
 * We opt to do OAuth 100% server-side. We need a way to pass the
 * authenticated user token to Electron, though. The IPC mechanism
 * for WebContent (especially for non-electron page hosted online) is
 * rather limited. The `AIcodes hack` we came up is to monitor URL changes,
 * and backend would issue a special redirection, appending user token
 * to the redirect URL so Electron can capture.
 *
 * HTTPS protocol ensures that the URL is as secure as the page content.
 */
/*
function captureUserToken(window, content) {
  // Issue an async request. Will be captured by the event above.
   content.on('did-navigate', (event, url) => {
   content.on('found-in-page', (foundEvent, result) => {
   console.log('... found in page event is triggered....');
   console.log(result);
   content.stopFindInPage('clearSelection');
   // window.loadURL(`file://${__dirname}/app.html`);
   });
   content.findInPage('nuts');
   });
  content.on('did-finish-load', () => {
    console.log('finished loading');
     content.on('found-in-page', (foundEvent, result) => {
     console.log('... found in page event is triggered....');
     console.log(result);
     content.stopFindInPage('clearSelection');
     // window.loadURL(`file://${__dirname}/app.html`);
     });
     content.findInPage('demo.*ze');
  });

  content.on('did-navigate', (event, url) => {
    const results = url.split('#');
    if (results.length > 1) {
      console.log(`User Access Token is: ${results[1]}.`);
    }
  });
}
*/

app.on('ready', () => {
  setApplicationMenu();

  const mainWindow = createWindow('main', {
    width: 500,
    height: 800,
  });

  mainWindow.loadURL(`file://${__dirname}/app.html`);
  // mainWindow.loadURL('https://www.ai.codes/oauth.html');
  const content = mainWindow.webContents;
  // captureUserToken(mainWindow, content);

  /*
   if (env.name === 'development') {
   mainWindow.openDevTools();
   } */

  // ==== Starts a local Ai.codes server ========
  // Pre-populating a bunch of frequently used classes.
  content.on('did-finish-load', () => {
    populateClasses(content);
  });

  const PORT = 26337;
  const expressServer = createServer(content, cache, isIncognitoClass);

  expressServer.listen(PORT, () => {
    // Callback triggered when server is successfully listening. Hurray!
    console.log('Server listening on: http://localhost:%s', PORT);
  });

  // Skip checking version update if it is not production.
  if (env.name === 'production') {
    configAutoUpdater(autoUpdater, content);
  }

  ipcMain.on('update-quit-install', () => {
    mainWindow.setClosable(true);
    autoUpdater.quitAndInstall();
  });

  // ====== ai.codes code ends =========
});

app.on('window-all-closed', () => {
  app.quit();
});

app.on('will-quit', () => {
  app.quit();
});

// Store the class -> extension (JSON object) mapping to cache.
ipcMain.on('ice-cache', (event, className, extension) => {
  cache.set(className, extension);
});

// Preferences
ipcMain.on('load-preference', (event) => {
  const result = config.get('preferences');
  if (result === undefined) {
    config.set('preferences', {incognito: []});
  }

  event.sender.send('update-preference-display', config.get('preferences'));
});

ipcMain.on('save-preference', (event, updatedPreferences) => {
  preferences = updatedPreferences;
  config.set('preferences', updatedPreferences);
});

<|endoftext|>


<commit_before>var activeIcons = {
  path: {
    '19': 'icons/active-19.png',
    '38': 'icons/active-38.png'
  }
};

var inactiveIcons = {
  path: {
    '19': 'icons/inactive-19.png',
    '38': 'icons/inactive-38.png'
  }
};

var active = false;

function toggleIcon() {
  chrome.browserAction.setIcon(active ? inactiveIcons : activeIcons);
  active = !active;
}

chrome.browserAction.onClicked.addListener(toggleIcon);
<commit_msg>Reduce redundancy be inspecting manifest<commit_after>var manifest = chrome.runtime.getManifest();

var inactiveIcons = manifest.browser_action.default_icon;
var activeIcons = {
  '19': 'icons/active-19.png',
  '38': 'icons/active-38.png'
};

var inactiveTitle = manifest.browser_action.default_title;
var activeTitle = 'Stop showing line lengths';

var active = false;

function toggleActiveState() {
  chrome.browserAction.setIcon({
    path: active ? inactiveIcons : activeIcons
  });

  chrome.browserAction.setTitle({
    title: active ? inactiveTitle : activeTitle
  });

  active = !active;
}

chrome.browserAction.onClicked.addListener(toggleActiveState);
<|endoftext|>


<commit_before>/* global chrome */
import liveReloadSocket from './livereload.js'

var badge = {
  badge: 'hide',
  badges: {
    hide: [''],
    ok: [' OK ', '#44992c'],
    no: [' NO ', '#f33'],
    connected: ['-(c-', [42,181,130,200]],
    // not using disconnect badge b/c visually dominating
    disconnected: ['-(  c-', [179,179,29,200]],
  },

  set: function (b){
    badge.badge = b
    chrome.browserAction
      .setBadgeText({text: this.badges[b][0]})
    if(this.badges[b][1])
      chrome.browserAction
        .setBadgeBackgroundColor({color:this.badges[b][1]})
  },

  tempSet: function (b, delay){
    var currB = badge.badge
    if (currB !== b){
      badge.set(b)
      badge.delay(currB, delay)
    }
  },

  delay: function (b, delay){
    setTimeout(function (){
      badge.set(b)
    }, delay||1200)
  },
}
// we'll start with disconnected badge
// badge.set('hide')

/////////////////////////////////////////////////////

function reloadExtensions(msg) {
  var app = msg.path

  // disable then enable 1 extension or app
  function reload (ext) {
    // false for disable, true for enable
    chrome.management.setEnabled(ext.id, false, function() {
      chrome.management.setEnabled(ext.id, true, function() {
        // func to tell extension it was auto-reloaded
        function forwardMsg(){
          chrome.runtime.sendMessage(ext.id, msg)
        }
        // apps still need launch
        if (ext.type.match(/app/))
          chrome.management.launchApp(ext.id, forwardMsg)
        else forwardMsg()
        console.log(ext.name + ' reloaded')
        // show an 'OK' badge
        badge.tempSet('ok')
      })
    })
  }

  chrome.management.getAll(function(extensions) {
    extensions = extensions.filter(function (ext){
      return (
        // installed as unpacked folder
        (ext.installType==='development')
        // if app not specified, only reload enabled
        && (app || ext.enabled===true)
        // restrict to app name or id if given
        // && ( (!app) || app===ext.name
        //   || app===ext.id)
        // Clerc shouldn't reload itself
        && (ext.id !==chrome.runtime.id)
      )
    })
    extensions.forEach(reload)
  })
}

//////////////////////////////////////////////

const messenger = {
  message (msg){
    console.log('messenger', msg)
    if (msg && msg.error)
      return onError(msg.error)
    reloadExtensions(msg)
  },
}

const onOpen = ()=> {
  console.log('connected to livereload')
  badge.set('ok')
  badge.delay('connected', 1200)
  chrome.browserAction.onClicked.removeListener(connect)
  chrome.browserAction.onClicked.addListener(disconnect)
}

const onClosed = ()=> {
  console.log('disconnected from livereload')
  badge.set('hide')
  chrome.browserAction.onClicked.removeListener(disconnect)
  chrome.browserAction.onClicked.addListener(connect)
}

const onError = err=> {
  badge.set('no')
  badge.delay('hide', 1200)
  console.error(err)
}

const lrSocket = liveReloadSocket({
  onOpen,
  onClosed,
  WebSocket,
  messenger,
  onError,
})

const connect = ()=> lrSocket.connect()
const disconnect = ()=> lrSocket.disconnect()
chrome.browserAction.onClicked.addListener(()=> lrSocket.connect())

////
<commit_msg>fix incorrectly named onClose<commit_after>/* global chrome */
import liveReloadSocket from './livereload.js'

var badge = {
  badge: 'hide',
  badges: {
    hide: [''],
    ok: [' OK ', '#44992c'],
    no: [' NO ', '#f33'],
    connected: ['-(c- ', [42,181,130,200]],
    // not using disconnect badge b/c visually dominating
    disconnected: ['-(  c-', [179,179,29,200]],
  },

  set: function (b){
    badge.badge = b
    chrome.browserAction
      .setBadgeText({text: this.badges[b][0]})
    if(this.badges[b][1])
      chrome.browserAction
        .setBadgeBackgroundColor({color:this.badges[b][1]})
  },

  tempSet: function (b, delay){
    var currB = badge.badge
    if (currB !== b){
      badge.set(b)
      badge.delay(currB, delay)
    }
  },

  delay: function (b, delay){
    setTimeout(function (){
      badge.set(b)
    }, delay||1200)
  },
}
// we'll start with disconnected badge
// badge.set('hide')

/////////////////////////////////////////////////////

function reloadExtensions(msg) {
  var app = msg.path

  // disable then enable 1 extension or app
  function reload (ext) {
    // false for disable, true for enable
    chrome.management.setEnabled(ext.id, false, function() {
      chrome.management.setEnabled(ext.id, true, function() {
        // func to tell extension it was auto-reloaded
        function forwardMsg(){
          chrome.runtime.sendMessage(ext.id, msg)
        }
        // apps still need launch
        if (ext.type.match(/app/))
          chrome.management.launchApp(ext.id, forwardMsg)
        else forwardMsg()
        console.log(ext.name + ' reloaded')
        // show an 'OK' badge
        badge.tempSet('ok')
      })
    })
  }

  chrome.management.getAll(function(extensions) {
    extensions = extensions.filter(function (ext){
      return (
        // installed as unpacked folder
        (ext.installType==='development')
        // if app not specified, only reload enabled
        && (app || ext.enabled===true)
        // restrict to app name or id if given
        // && ( (!app) || app===ext.name
        //   || app===ext.id)
        // Clerc shouldn't reload itself
        && (ext.id !==chrome.runtime.id)
      )
    })
    extensions.forEach(reload)
  })
}

//////////////////////////////////////////////

const messenger = {
  message (msg){
    console.log('messenger', msg)
    if (msg && msg.error)
      return onError(msg.error)
    reloadExtensions(msg)
  },
}

const onOpen = ()=> {
  console.log('connected to livereload')
  badge.set('ok')
  badge.delay('connected', 1200)
  chrome.browserAction.onClicked.removeListener(connect)
  chrome.browserAction.onClicked.addListener(disconnect)
}

const onClose = ()=> {
  console.log('disconnected from livereload')
  badge.set('hide')
  chrome.browserAction.onClicked.removeListener(disconnect)
  chrome.browserAction.onClicked.addListener(connect)
}

const onError = err=> {
  badge.set('no')
  badge.delay('hide', 1200)
  console.error(err)
}

const lrSocket = liveReloadSocket({
  onOpen,
  onClose,
  WebSocket,
  messenger,
  onError,
})

const connect = ()=> lrSocket.connect()
const disconnect = ()=> lrSocket.disconnect()
chrome.browserAction.onClicked.addListener(()=> lrSocket.connect())

////
<|endoftext|>


<commit_before>//Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

import UIContainerPlugin from '../../base/ui_container_plugin'
import Events from '../../base/events'
import template from '../../base/template'
import Playback from '../../base/playback'
import posterHTML from './public/poster.html'
import playIcon from '../../icons/01-play.svg'
import './public/poster.scss'

export default class PosterPlugin extends UIContainerPlugin {
  get name() { return 'poster' }
  get template() { return template(posterHTML) }
  get shouldRender() {
    const showForNoOp = !!(this.options.poster && this.options.poster.showForNoOp)
    return this.container.playback.name !== 'html_img' && (this.container.playback.getPlaybackType() !== Playback.NO_OP || showForNoOp)
  }

  get attributes() {
    return {
      'class': 'player-poster',
      'data-poster': ''
    }
  }

  get events() {
    return {
      'click': 'clicked'
    }
  }

  get showOnVideoEnd() {
    return !this.options.poster || this.options.poster.showOnVideoEnd || this.options.poster.showOnVideoEnd === undefined
  }

  constructor(container) {
    super(container)
    this.hasStartedPlaying = false
    this.playRequested = false
    this.render()
    process.nextTick(() => this.update())
  }

  bindEvents() {
    this.listenTo(this.container, Events.CONTAINER_STOP, this.onStop)
    this.listenTo(this.container, Events.CONTAINER_PLAY, this.onPlay)
    this.listenTo(this.container, Events.CONTAINER_STATE_BUFFERING, this.update)
    this.listenTo(this.container, Events.CONTAINER_STATE_BUFFERFULL, this.update)
    this.listenTo(this.container, Events.CONTAINER_OPTIONS_CHANGE, this.render)
    this.showOnVideoEnd && this.listenTo(this.container, Events.CONTAINER_ENDED, this.onStop)
  }

  onPlay() {
    this.hasStartedPlaying = true
    this.update()
  }

  onStop() {
    this.hasStartedPlaying = false
    this.playRequested = false
    this.update()
  }

  updatePlayButton(show) {
    if (show && (!this.options.chromeless || this.options.allowUserInteraction))
      this.showPlayButton()
    else
      this.hidePlayButton()
  }

  showPlayButton() {
    this.$playButton.show()
    this.$el.addClass('clickable')
  }

  hidePlayButton() {
    this.$playButton.hide()
    this.$el.removeClass('clickable')
  }

  clicked() {
    if (!this.options.chromeless || this.options.allowUserInteraction) {
      this.playRequested = true
      this.update()
      this.container.play()
    }
    return false
  }

  shouldHideOnPlay() {
    // Audio broadcasts should keep the poster up; video should hide poster while playing.
    return !this.container.playback.isAudioOnly
  }

  update() {
    if (!this.shouldRender)
      return

    let showPlayButton = !this.playRequested  && !this.hasStartedPlaying && !this.container.buffering
    this.updatePlayButton(showPlayButton)
    this.updatePoster()
  }

  updatePoster() {
    if (!this.hasStartedPlaying) this.showPoster()
    else this.hidePoster()
  }

  showPoster() {
    this.container.disableMediaControl()
    this.$el.show()
  }

  hidePoster() {
    this.container.enableMediaControl()
    if (this.shouldHideOnPlay())
      this.$el.hide()
  }

  render() {
    if (!this.shouldRender)
      return

    this.$el.html(this.template())

    const isRegularPoster = this.options.poster && this.options.poster.custom === undefined

    if (isRegularPoster) {
      const posterUrl = this.options.poster.url || this.options.poster
      this.$el.css({ 'background-image': 'url(' + posterUrl + ')' })
    } else if (this.options.poster) { this.$el.css({ 'background': this.options.poster.custom }) }

    this.container.$el.append(this.el)
    this.$playWrapper = this.$el.find('.play-wrapper')
    this.$playWrapper.append(playIcon)
    this.$playButton = this.$playWrapper.find('svg')
    this.$playButton.addClass('poster-icon')
    this.$playButton.attr('data-poster', '')

    let buttonsColor = this.options.mediacontrol && this.options.mediacontrol.buttons
    if (buttonsColor)
      this.$el.find('svg path').css('fill', buttonsColor)

    if (this.options.mediacontrol && this.options.mediacontrol.buttons) {
      buttonsColor = this.options.mediacontrol.buttons
      this.$playButton.css('color', buttonsColor)
    }
    this.update()
    return this
  }
}
<commit_msg>refactor(poster): do not show play poster button when there is fatal error<commit_after>//Copyright 2014 Globo.com Player authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

import UIContainerPlugin from '../../base/ui_container_plugin'
import Events from '../../base/events'
import template from '../../base/template'
import Playback from '../../base/playback'
import PlayerError from '../../components/error/error'
import posterHTML from './public/poster.html'
import playIcon from '../../icons/01-play.svg'
import './public/poster.scss'

export default class PosterPlugin extends UIContainerPlugin {
  get name() { return 'poster' }
  get template() { return template(posterHTML) }
  get shouldRender() {
    const showForNoOp = !!(this.options.poster && this.options.poster.showForNoOp)
    return this.container.playback.name !== 'html_img' && (this.container.playback.getPlaybackType() !== Playback.NO_OP || showForNoOp)
  }

  get attributes() {
    return {
      'class': 'player-poster',
      'data-poster': ''
    }
  }

  get events() {
    return {
      'click': 'clicked'
    }
  }

  get showOnVideoEnd() {
    return !this.options.poster || this.options.poster.showOnVideoEnd || this.options.poster.showOnVideoEnd === undefined
  }

  constructor(container) {
    super(container)
    this.hasStartedPlaying = false
    this.playRequested = false
    this.render()
    process.nextTick(() => this.update())
  }

  bindEvents() {
    this.listenTo(this.container, Events.CONTAINER_STOP, this.onStop)
    this.listenTo(this.container, Events.CONTAINER_PLAY, this.onPlay)
    this.listenTo(this.container, Events.CONTAINER_STATE_BUFFERING, this.update)
    this.listenTo(this.container, Events.CONTAINER_STATE_BUFFERFULL, this.update)
    this.listenTo(this.container, Events.CONTAINER_OPTIONS_CHANGE, this.render)
    this.listenTo(this.container, Events.CONTAINER_ERROR, this.onError)
    this.showOnVideoEnd && this.listenTo(this.container, Events.CONTAINER_ENDED, this.onStop)
  }

  onError(error) {
    if (error.level == PlayerError.Levels.FATAL) {
      this.hasFatalError = true
      this.hidePlayButton()
    }
  }

  onPlay() {
    this.hasStartedPlaying = true
    this.update()
  }

  onStop() {
    this.hasStartedPlaying = false
    this.playRequested = false
    this.update()
  }

  updatePlayButton(show) {
    if (show && (!this.options.chromeless || this.options.allowUserInteraction))
      this.showPlayButton()
    else
      this.hidePlayButton()
  }

  showPlayButton() {
    if (this.hasFatalError) return

    this.$playButton.show()
    this.$el.addClass('clickable')
  }

  hidePlayButton() {
    this.$playButton.hide()
    this.$el.removeClass('clickable')
  }

  clicked() {
    if (!this.options.chromeless || this.options.allowUserInteraction) {
      this.playRequested = true
      this.update()
      this.container.play()
    }
    return false
  }

  shouldHideOnPlay() {
    // Audio broadcasts should keep the poster up; video should hide poster while playing.
    return !this.container.playback.isAudioOnly
  }

  update() {
    if (!this.shouldRender)
      return

    let showPlayButton = !this.playRequested  && !this.hasStartedPlaying && !this.container.buffering
    this.updatePlayButton(showPlayButton)
    this.updatePoster()
  }

  updatePoster() {
    if (!this.hasStartedPlaying) this.showPoster()
    else this.hidePoster()
  }

  showPoster() {
    this.container.disableMediaControl()
    this.$el.show()
  }

  hidePoster() {
    this.container.enableMediaControl()
    if (this.shouldHideOnPlay())
      this.$el.hide()
  }

  render() {
    if (!this.shouldRender)
      return

    this.$el.html(this.template())

    const isRegularPoster = this.options.poster && this.options.poster.custom === undefined

    if (isRegularPoster) {
      const posterUrl = this.options.poster.url || this.options.poster
      this.$el.css({ 'background-image': 'url(' + posterUrl + ')' })
    } else if (this.options.poster) { this.$el.css({ 'background': this.options.poster.custom }) }

    this.container.$el.append(this.el)
    this.$playWrapper = this.$el.find('.play-wrapper')
    this.$playWrapper.append(playIcon)
    this.$playButton = this.$playWrapper.find('svg')
    this.$playButton.addClass('poster-icon')
    this.$playButton.attr('data-poster', '')

    let buttonsColor = this.options.mediacontrol && this.options.mediacontrol.buttons
    if (buttonsColor)
      this.$el.find('svg path').css('fill', buttonsColor)

    if (this.options.mediacontrol && this.options.mediacontrol.buttons) {
      buttonsColor = this.options.mediacontrol.buttons
      this.$playButton.css('color', buttonsColor)
    }
    this.update()
    return this
  }
}
<|endoftext|>


<commit_before>var Template = function (tpl, data) {
    tpl = tpl.split('\n').map(function (s) {return s.trim();}).join('').replace(/[\t\n\r]/g, '').replace(/"/g, '\'');
    var ifSta = /<(\S*?) [^>]*lk-if='([^\']*)'[^>]*>(.*)<\/\1>/g;
    var notSta = /<(\S*?) [^>]*lk-not='([^\']*)'[^>]*>(.*)<\/\1>/g;
    var loop = /<(\S*?) [^>]*lk-for='([^\']*)'[^>]*>(.*)<\/\1>/g;
    var html = /\{\{\{([^\}\}\}]+)?\}\}\}/g;
    var value = /\{\{([^\}\}]+)?\}\}(?=[^}])/g;
    var tagPair = function (str, mode) {
        var subSection = [], ts = [], _m, _tag, cursor = 0;
        var re = new RegExp("<([^>]*?) [^>]*lk-"+ mode +"='([^\']*)'[^>]*>");
        var updateTag = function (s) {
            s = s || '';
            var temp = s.match(re);
            var reStart = temp ? temp[1] : '';
            _tag = new RegExp('<' + reStart + '|<\/'+ reStart + '>', 'g');
        };
        var restStr = str;
        updateTag(restStr);
        while (_m = _tag.exec(restStr)) {
            var tagName = _m[0];
            if (/<\/.*/.test(tagName)) ts.pop();
            else ts.push(tagName);
            if (!ts.length) {
                subSection.push(restStr.slice(cursor, cursor = _m.index + tagName.length));
                restStr = restStr.slice(cursor);
                cursor = 0;
                updateTag(restStr);
            }
        }
        subSection.push(restStr);
        return subSection;
    };
    var convertControl = function (str) {
        var _map = {
            'if': ifSta,
            'not': notSta
        };
        var _op = '';
        var _t = function (sub) {
            return sub.replace(_map[_op], function (m, tag, _c) {
                _c = 'this.' + _c.replace(/\{|\}/g, '');
                if (_op === 'if') {
                    if ((new Function('return ' + _c)).apply(data) === false) return "";
                }
                if (_op === 'not')
                    if ((new Function('return ' + _c)).apply(data) !== false) return "";
                return m;
            });
        };
        str = tagPair(str, _op = 'if').map(_t).join('');
        str = tagPair(str, _op = 'not').map(_t).join('');
        return str;
    };
    var convertLoop = function (str, layer) {
        var subs = tagPair(str, 'for');
        return subs.map(function (sub) {
            if (!sub) return '';
            return (
            sub.replace(loop, function (m, tag, _c, _sta) {
                var innerSta = _sta;
                layer++;
                if (loop.test(_sta)) {
                    innerSta = convertLoop(_sta, layer);
                }
                var cv = _c.split(' '), e = cv[0], es = cv[2];
                return m.replace(_sta, function () {
                    var tempS = innerSta.replace(new RegExp('{{ *' + '(' + e + ')([^\}]*)' + ' *}}', 'g'), function (m, _e, _suf) {
                        console.log(m);
                        return '{{' + es + '[i'+ layer +']' + _suf +'}}'
                    });
                    tempS = tempS.replace(new RegExp('this.('+ e +')(.*).length', 'g'), function (m, _e, _suf) {
                        return 'this.' + es + '[i'+ layer +']'+ _suf +'.length';
                    });
                    var tempC = 'this.' + es;
                    return '");\nfor(var i' + layer +' = 0; i'+ layer +' < '+ tempC + '.length; i'+ layer +'++) {\n\ts.push("' + tempS + '");\n}\ns.push("';
                });
            }));
        }).join('');
    };
    var convertValue = function (str) {
        return str.replace(value, function (m, g) {
            return '" + handleValue(this.' + g.trim() + ') + "';
        });
    };
    var convertHTML = function (str) {
        return str.replace(html, function (m, g) {
            return '" + handleHTML(this.' + g.trim() + ') + "';
        })
    };
    var pre = 'var handleValue = function(value) {if (value) {return value.replace(/>/g, ">").replace(/</g, "<");} return "";}; var handleHTML = function(value) {if (value) {return value;} return "";}; var s = [];';
    var suf = 'return s.join("");';
    body = convertControl(tpl);
    body = 's.push("' + convertLoop(body, -1)  + '");';
    console.log(body);
    body = convertValue(body);
    body = convertHTML(body);
    body = pre + body + suf;
    return (new Function(body.replace(/[\t\n\r]/g, ''))).apply(data).replace(/'/g, '"');
};

module.exports = Template;<commit_msg>add unescaped mode<commit_after>var Template = function (tpl, data) {
    tpl = tpl.split('\n').map(function (s) {return s.trim();}).join('').replace(/[\t\n\r]/g, '').replace(/"/g, '\'');
    var ifSta = /<(\S*?) [^>]*lk-if='([^\']*)'[^>]*>(.*)<\/\1>/g;
    var notSta = /<(\S*?) [^>]*lk-not='([^\']*)'[^>]*>(.*)<\/\1>/g;
    var loop = /<(\S*?) [^>]*lk-for='([^\']*)'[^>]*>(.*)<\/\1>/g;
    var html = /\{\{\{([^\}\}\}]+)?\}\}\}/g;
    var value = /\{\{([^\}\}]+)?\}\}(?=[^}])/g;
    var tagPair = function (str, mode) {
        var subSection = [], ts = [], _m, _tag, cursor = 0;
        var re = new RegExp("<([^>]*?) [^>]*lk-"+ mode +"='([^\']*)'[^>]*>");
        var updateTag = function (s) {
            s = s || '';
            var temp = s.match(re);
            var reStart = temp ? temp[1] : '';
            _tag = new RegExp('<' + reStart + '|<\/'+ reStart + '>', 'g');
        };
        var restStr = str;
        updateTag(restStr);
        while (_m = _tag.exec(restStr)) {
            var tagName = _m[0];
            if (/<\/.*/.test(tagName)) ts.pop();
            else ts.push(tagName);
            if (!ts.length) {
                subSection.push(restStr.slice(cursor, cursor = _m.index + tagName.length));
                restStr = restStr.slice(cursor);
                cursor = 0;
                updateTag(restStr);
            }
        }
        subSection.push(restStr);
        return subSection;
    };
    var convertControl = function (str) {
        var _map = {
            'if': ifSta,
            'not': notSta
        };
        var _op = '';
        var _t = function (sub) {
            return sub.replace(_map[_op], function (m, tag, _c) {
                _c = 'this.' + _c.replace(/\{|\}/g, '');
                if (_op === 'if') {
                    if ((new Function('return ' + _c)).apply(data) === false) return "";
                }
                if (_op === 'not')
                    if ((new Function('return ' + _c)).apply(data) !== false) return "";
                return m;
            });
        };
        str = tagPair(str, _op = 'if').map(_t).join('');
        str = tagPair(str, _op = 'not').map(_t).join('');
        return str;
    };
    var convertLoop = function (str, layer) {
        var subs = tagPair(str, 'for');
        return subs.map(function (sub) {
            if (!sub) return '';
            return (
            sub.replace(loop, function (m, tag, _c, _sta) {
                var innerSta = _sta;
                layer++;
                if (loop.test(_sta)) {
                    innerSta = convertLoop(_sta, layer);
                }
                var cv = _c.split(' '), e = cv[0], es = cv[2];
                return m.replace(_sta, function () {
                    var tempS = innerSta.replace(new RegExp('{{ *' + '(' + e + ')([^\}]*)' + ' *}}', 'g'), function (m, _e, _suf) {
                        console.log(m);
                        return '{{' + es + '[i'+ layer +']' + _suf +'}}'
                    });
                    tempS = tempS.replace(new RegExp('this.('+ e +')(.*).length', 'g'), function (m, _e, _suf) {
                        return 'this.' + es + '[i'+ layer +']'+ _suf +'.length';
                    });
                    var tempC = 'this.' + es;
                    return '");\nfor(var i' + layer +' = 0; i'+ layer +' < '+ tempC + '.length; i'+ layer +'++) {\n\ts.push("' + tempS + '");\n}\ns.push("';
                });
            }));
        }).join('');
    };
    var convertValue = function (str) {
        return str.replace(value, function (m, g) {
            return '" + handleValue(this.' + g.trim() + ') + "';
        });
    };
    var convertHTML = function (str) {
        return str.replace(html, function (m, g) {
            return '" + handleHTML(this.' + g.trim() + ') + "';
        })
    };
    var pre = 'var handleValue = function(value) {if (value) {return value.replace(/>/g, ">").replace(/</g, "<");} return "";}; var handleHTML = function(value) {if (value) {return value;} return "";}; var s = [];';
    var suf = 'return s.join("");';
    body = convertControl(tpl);
    body = 's.push("' + convertLoop(body, -1)  + '");';
    body = convertValue(body);
    body = convertHTML(body);
    body = pre + body + suf;
    return (new Function(body.replace(/[\t\n\r]/g, ''))).apply(data).replace(/'/g, '"');
};

module.exports = Template;<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { ListView, View } from 'react-native';

import { connectStyle } from '@shoutem/theme';
import mapPropsToStyleNames from '../Utils/mapPropsToStyleNames';

class List extends Component {

  renderChildren() {
    const childrenArray = React.Children.map(this.props.children, child => child);

    return childrenArray;
  }

  render() {
    if (this.props.dataArray && this.props.renderRow) {
      const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
      const dataSource = ds.cloneWithRows(this.props.dataArray);
      return (
        <ListView
          {...this.props}
          enableEmptySections
          dataSource={dataSource}
          renderRow={this.props.renderRow}
        />
      );
    }
    return (
      <View ref={c => this._root = c} {...this.props} >
        {this.renderChildren()}
      </View>
    );
  }

}
const StyledList = connectStyle('NativeBase.List', {}, mapPropsToStyleNames)(List);

export {
  StyledList as List,
};
<commit_msg>List implementation fix #601<commit_after>import React, { Component } from 'react';
import { ListView, View } from 'react-native';

import { connectStyle } from '@shoutem/theme';
import mapPropsToStyleNames from '../Utils/mapPropsToStyleNames';

class List extends Component {

  constructor(props) {
    super(props);
    const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
    this.state = {
      dataSource: ds.cloneWithRows(this.props.dataArray)
    }
  }
  componentWillReceiveProps(nextProps) {
    const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
    this.setState({
      dataSource: ds.cloneWithRows(nextProps.dataArray)
    });
  }
  renderChildren() {
    const childrenArray = React.Children.map(this.props.children, child => child);

    return childrenArray;
  }

  render() {
    if (this.props.dataArray && this.props.renderRow) {
      return (
        <ListView
          {...this.props}
          enableEmptySections
          dataSource={this.state.dataSource}
          renderRow={this.props.renderRow}
        />
      );
    }
    return (
      <View ref={c => this._root = c} {...this.props} >
        {this.renderChildren()}
      </View>
    );
  }

}
const StyledList = connectStyle('NativeBase.List', {}, mapPropsToStyleNames)(List);

export {
  StyledList as List,
};
<|endoftext|>


<commit_before>import linearSystem from '../index.js'
import sinon from 'sinon'
describe('linearSystem', () => {
    let linSys;
    let data;
    beforeEach(function() {
        linSys = new linearSystem();
        data = {
          s : [[2,2,6],[9,9,30]]
        };
    });

    describe('_switch', () => {
      it('should exchange places of two diffrent rows', () => {
        let thing = linSys._switch(data,0,1);
        expect(thing.s).toEqual([[9,9,30],[2,2,6]]);
        //mutation check
      });

      it('mutation check', () => {
        let thing = linSys._switch(data,0,1);
        expect(thing.s).toEqual([[9,9,30],[2,2,6]]);
        expect(data).toEqual({ s : [[2,2,6],[9,9,30]]});
      });
    });

    describe("_getRowScaledBy", () => {
      it('should return array mulitplied by scale', () => {
        let row = linSys._getRowScaledBy([2,0,6],2);
        expect(row).toEqual([4,0,12]);
      });

      it('should return array mulitplied to negitive scale', () => {
        let row = linSys._getRowScaledBy([2,0,-6],-1);
        expect(row).toEqual([-2,0,6]);
      });

      it('mutation check', () => {
        let row = linSys._getRowScaledBy([2,0,-6],-1);
        expect(data).toEqual({s : [[2,2,6],[9,9,30]]});
      });
    });

    describe("_rowReplacement", () => {
      it('should call _getRowScaledBy with data', () => {
        let scaledBy = sinon.spy(linSys, '_getRowScaledBy');
        let rowToBeReplaced = 0, otherRow = 1, scale = 2;
        linSys._rowReplacement(data, rowToBeReplaced, otherRow, scale);
        scaledBy.restore();
        sinon.assert.calledWith(scaledBy, [9,9,30], 2);
      });

      it('should return array with a row replaced by itself mulitplied to scale', () => {
        let rowToBeReplaced = 0,otherRow = 1,scale = 2;
        let newthing = linSys._rowReplacement(data, rowToBeReplaced, otherRow, scale);
        expect(newthing).toEqual({s : [[20,20,66],[9,9,30]]});
      });

      it('mutation test', () => {
        let rowToBeReplaced = 0, otherRow = 1, scale = 2;
        linSys._rowReplacement(data, rowToBeReplaced, otherRow, scale);
        expect(data).toEqual({ s : [[2,2,6],[9,9,30]]});
      });
    });

    describe("_largestAbsoluteMovedToTopOfColumn", () => {
      it('should return array with largest absolute value to top of each pivot', () => {
        let inputSystem = {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let expectedOutput = {
          s : [
            [-3,2,1,5],
            [1,2,3,4],
            [0,1,2,3]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let output = linSys._largestAbsoluteMovedToTopOfColumn(inputSystem);
        expect(output).toEqual(expectedOutput);
      });

      it("calls _switch with correct values", () => {
        let switchy = sinon.spy(linSys, '_switch');
        let inputSystem = {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let output = linSys._largestAbsoluteMovedToTopOfColumn(inputSystem);
        switchy.restore();
        sinon.assert.calledWith(switchy, {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        });
      });

      it("mutation check", () => {
        let inputSystem = {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        linSys._largestAbsoluteMovedToTopOfColumn(inputSystem);
        expect(inputSystem).toEqual({
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        });
      });
    });

    describe("_zeroAllRowsUnderThePivot", () => {
      it('returns correct value', () => {
        let inputSystem = {
          s : [
            [5,1,1,10],
            [-1,1,1,-2],
            [1,1,1,2]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let outSystem = linSys._zeroAllRowsUnderThePivot(inputSystem);
        expect(outSystem.s).toEqual(
          [
            [ 5, 1, 1, 10 ],
            [ 0, 1.2, 1.2, 0 ],
            [ 0, 0.8, 0.8, 0 ]
          ]);
      });

      it('mutation check', () => {
        let inputSystem = {
          s : [
            [5,1,1,10],
            [-1,1,1,-2],
            [1,1,1,2]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let outSystem = linSys._zeroAllRowsUnderThePivot(inputSystem);
        expect(inputSystem).toEqual({
          s : [
            [5,1,1,10],
            [-1,1,1,-2],
            [1,1,1,2]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        });
      });

      it("calls _rowReplacementRemover with correct values", () => {
        let replacer = sinon.spy(linSys, '_rowReplacementRemover');
        let inputSystem = {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let outSystem = linSys._zeroAllRowsUnderThePivot(inputSystem);
        replacer.restore();
        sinon.assert.calledWithExactly(replacer, {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        },
      1);
      });
    });

    describe("_zeroAllRowsAboveThePivot", () => {
      it("should return correct output", () => {
        let inputSystem = {
          s : [
            [5,3,4,10],
            [0,5,7,14],
            [0,0,2,54],
          ],
          pivot:{row:2,column:2}
        };
        let outputSystem = linSys._zeroAllRowsAboveThePivot(inputSystem);
        expect(outputSystem).toEqual({
          s:[
            [ 5, 3, 0, -98 ],
            [ 0, 5, 0, -175 ],
            [ 0, 0, 2, 54 ]
          ],
          pivot:{row:2,column:2}});
      });
    });

    it('mutation check', () => {
      let inputSystem = {
        s : [
          [5,3,4,10],
          [0,5,7,14],
          [0,0,2,54],
        ],
        pivot:{row:2,column:2}
      };
      let outputSystem = linSys._zeroAllRowsAboveThePivot(inputSystem);
      expect(inputSystem).toEqual({
        s : [
          [5,3,4,10],
          [0,5,7,14],
          [0,0,2,54],
        ],
        pivot:{row:2,column:2}
      });

    it("calls _rowReplacementRemover with correct values", () => {
      let replacer = sinon.spy(linSys, '_rowReplacementRemover');
      let inputSystem = {
        s : [
          [1,2,3,5],
          [0,2,1,5],
          [0,0,5,5]
        ],
        pivot : {row:2,column:2}
      };
      let outSystem = linSys._zeroAllRowsUnderThePivot(inputSystem);
      replacer.restore();
      sinon.assert.calledWithExactly(replacer, {
        s : [
          [1,2,3,5],
          [0,2,1,5],
          [0,0,5,5]
        ],
        pivot : {row:2,column:2}
      },
    1);
    });
  });

    describe("_scalePivotToOne", () => {
      it("returns expected value", () => {
        let testSystem = {
          s : [
            [3,0,0,3],
            [0,2,1,5],
            [0,5,6,7,]
          ],
          pivot : {row:0,column:0}
        };
        let outSystem = linSys._scalePivotToOne(testSystem);
        expect(outSystem).toEqual({
          s : [
            [1,0,0,1],
            [0,2,1,5],
            [0,5,6,7,]
          ],
          pivot : {row:0,column:0}
        });
      });
    });

});
<commit_msg>more testing<commit_after>import linearSystem from '../index.js'
import sinon from 'sinon'
describe('linearSystem', () => {
    let linSys;
    let data;
    beforeEach(function() {
        linSys = new linearSystem();
        data = {
          s : [[2,2,6],[9,9,30]]
        };
    });

    describe('_switch', () => {
      it('should exchange places of two diffrent rows', () => {
        let thing = linSys._switch(data,0,1);
        expect(thing.s).toEqual([[9,9,30],[2,2,6]]);
        //mutation check
      });

      it('mutation check', () => {
        let thing = linSys._switch(data,0,1);
        expect(thing.s).toEqual([[9,9,30],[2,2,6]]);
        expect(data).toEqual({ s : [[2,2,6],[9,9,30]]});
      });
    });

    describe("_getRowScaledBy", () => {
      it('should return array mulitplied by scale', () => {
        let row = linSys._getRowScaledBy([2,0,6],2);
        expect(row).toEqual([4,0,12]);
      });

      it('should return array mulitplied to negitive scale', () => {
        let row = linSys._getRowScaledBy([2,0,-6],-1);
        expect(row).toEqual([-2,0,6]);
      });

      it('mutation check', () => {
        let row = linSys._getRowScaledBy([2,0,-6],-1);
        expect(data).toEqual({s : [[2,2,6],[9,9,30]]});
      });
    });

    describe("_rowReplacement", () => {
      it('should call _getRowScaledBy with data', () => {
        let scaledBy = sinon.spy(linSys, '_getRowScaledBy');
        let rowToBeReplaced = 0, otherRow = 1, scale = 2;
        linSys._rowReplacement(data, rowToBeReplaced, otherRow, scale);
        scaledBy.restore();
        sinon.assert.calledWith(scaledBy, [9,9,30], 2);
      });

      it('should return array with a row replaced by itself mulitplied to scale', () => {
        let rowToBeReplaced = 0,otherRow = 1,scale = 2;
        let newthing = linSys._rowReplacement(data, rowToBeReplaced, otherRow, scale);
        expect(newthing).toEqual({s : [[20,20,66],[9,9,30]]});
      });

      it('mutation test', () => {
        let rowToBeReplaced = 0, otherRow = 1, scale = 2;
        linSys._rowReplacement(data, rowToBeReplaced, otherRow, scale);
        expect(data).toEqual({ s : [[2,2,6],[9,9,30]]});
      });
    });

    describe("_largestAbsoluteMovedToTopOfColumn", () => {
      it('should return array with largest absolute value to top of each pivot', () => {
        let inputSystem = {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let expectedOutput = {
          s : [
            [-3,2,1,5],
            [1,2,3,4],
            [0,1,2,3]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let output = linSys._largestAbsoluteMovedToTopOfColumn(inputSystem);
        expect(output).toEqual(expectedOutput);
      });

      it("calls _switch with correct values", () => {
        let switchy = sinon.spy(linSys, '_switch');
        let inputSystem = {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let output = linSys._largestAbsoluteMovedToTopOfColumn(inputSystem);
        switchy.restore();
        sinon.assert.calledWith(switchy, {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        });
      });

      it("mutation check", () => {
        let inputSystem = {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        linSys._largestAbsoluteMovedToTopOfColumn(inputSystem);
        expect(inputSystem).toEqual({
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        });
      });
    });

    describe("_zeroAllRowsUnderThePivot", () => {
      it('returns correct value', () => {
        let inputSystem = {
          s : [
            [5,1,1,10],
            [-1,1,1,-2],
            [1,1,1,2]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let outSystem = linSys._zeroAllRowsUnderThePivot(inputSystem);
        expect(outSystem.s).toEqual(
          [
            [ 5, 1, 1, 10 ],
            [ 0, 1.2, 1.2, 0 ],
            [ 0, 0.8, 0.8, 0 ]
          ]);
      });

      it('mutation check', () => {
        let inputSystem = {
          s : [
            [5,1,1,10],
            [-1,1,1,-2],
            [1,1,1,2]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let outSystem = linSys._zeroAllRowsUnderThePivot(inputSystem);
        expect(inputSystem).toEqual({
          s : [
            [5,1,1,10],
            [-1,1,1,-2],
            [1,1,1,2]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        });
      });

      it("calls _rowReplacementRemover with correct values", () => {
        let replacer = sinon.spy(linSys, '_rowReplacementRemover');
        let inputSystem = {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        };
        let outSystem = linSys._zeroAllRowsUnderThePivot(inputSystem);
        replacer.restore();
        sinon.assert.calledWithExactly(replacer, {
          s : [
            [0,1,2,3],
            [1,2,3,4],
            [-3,2,1,5]
          ],
          pivot : {
            column : 0,
            row : 0
          }
        },
      1);
      });
    });

    describe("_zeroAllRowsAboveThePivot", () => {
      it("should return correct output", () => {
        let inputSystem = {
          s : [
            [5,3,4,10],
            [0,5,7,14],
            [0,0,2,54],
          ],
          pivot:{row:2,column:2}
        };
        let outputSystem = linSys._zeroAllRowsAboveThePivot(inputSystem);
        expect(outputSystem).toEqual({
          s:[
            [ 5, 3, 0, -98 ],
            [ 0, 5, 0, -175 ],
            [ 0, 0, 2, 54 ]
          ],
          pivot:{row:2,column:2}});
      });
    });

    it('mutation check', () => {
      let inputSystem = {
        s : [
          [5,3,4,10],
          [0,5,7,14],
          [0,0,2,54],
        ],
        pivot:{row:2,column:2}
      };
      let outputSystem = linSys._zeroAllRowsAboveThePivot(inputSystem);
      expect(inputSystem).toEqual({
        s : [
          [5,3,4,10],
          [0,5,7,14],
          [0,0,2,54],
        ],
        pivot:{row:2,column:2}
      });

    it("calls _rowReplacementRemover with correct values", () => {
      let replacer = sinon.spy(linSys, '_rowReplacementRemover');
      let inputSystem = {
        s : [
          [1,2,3,5],
          [0,2,1,5],
          [0,0,5,5]
        ],
        pivot : {row:2,column:2}
      };
      let outSystem = linSys._zeroAllRowsUnderThePivot(inputSystem);
      replacer.restore();
      sinon.assert.calledWithExactly(replacer, {
        s : [
          [1,2,3,5],
          [0,2,1,5],
          [0,0,5,5]
        ],
        pivot : {row:2,column:2}
      },
    1);
    });
  });

    describe("_scalePivotToOne", () => {
      it("returns expected value", () => {
        let testSystem = {
          s : [
            [3,0,0,3],
            [0,2,1,5],
            [0,5,6,7,]
          ],
          pivot : {row:0,column:0}
        };
        let outSystem = linSys._scalePivotToOne(testSystem);
        expect(outSystem).toEqual({
          s : [
            [1,0,0,1],
            [0,2,1,5],
            [0,5,6,7,]
          ],
          pivot : {row:0,column:0}
        });
      });
      it('should call _getRowScaledBy with correct values', () => {
        let inputSystem = {
          s : [
            [2,0,0,2],
            [0,2,1,5],
            [0,5,6,7,]
          ],
          pivot : {row:0,column:0}
        };
        let replacer = sinon.spy(linSys, "_scalePivotToOne");
        linSys._scalePivotToOne(inputSystem);
        replacer.calledWithExactly([2,0,0,2], .5);
      });
    });

});
<|endoftext|>


<commit_before>(function (factory) {
	if (typeof define === 'function' && define.amd) {
		define(['basil.js'], factory); // AMD
	} else if (typeof exports === 'object') {
		module.exports = factory(require( './basil.js')); // Node
	} else {
		factory(window.Basil); // Browser global
	}
}(function (Basil) {
	var BasilList = function (options) {
	return new Basil.utils.extend(Basil.Storage().init(options), Basil.List(options));
	};

	Basil.List = function () {
		var _toIndex = function (index, length) {
			if (index < 0)
				index = length + index;

			if (index < 0 || index >= length)
				throw new Error("ERR index out of range");

			return index;
		};

		return {
			_listPlugin: true,
			blpop: function () {
				throw new Error('not implemented yet');
			},
			brpop: function () {
				throw new Error('not implemented yet');
			},
			brpoplpush: function (source, destination) {
				throw new Error('not implemented yet');
			},
			lindex: function (key, index) {
				var list = this.get(key) || [];

				try {
					index = _toIndex(index, list.length);
				} catch (e) {
					return null;
				}

				return list[index];
			},
			linsert: function (key, where, pivot, value) {
				var index = -1,
					list = this.get(key) || [];

				if (0 === list.length)
					return 0;

				if ('undefined' === typeof value || 'undefined' === typeof pivot)
					throw new Error('ERR wrong number of arguments for \'linsert\' command');

				if ('BEFORE' !== where && 'AFTER' !== where)
					throw new Error('ERR syntax error');

				// added here for Basil, even if objects are supported
				// we to not support (yet?) object comparison, too heavy
				if ('number' !== typeof pivot && 'string' !== typeof pivot)
					throw new Error('ERR syntax error');

				for (var i = 0; i < list.length; i++) {
					if (pivot === list[i]) {
						index = i;
						break;
					}
				}

				if (-1 === index)
					return index;

				list.splice('AFTER' === where ? i - 1 : i, 0, value);
				this.set(key, list);

				return list.length;
			},
			llen: function (key) {
				return (this.get(key) || []).length;
			},
			lpop: function (key) {
				var list = this.get(key) || [],
					value = list.shift();

				if (0 === list.length)
					this.remove(key);
				else
					this.set(key, list);

				return value || null;
			},
			lpush: function (key, value) {
				var list = this.get(key) || [];
				list.unshift(value);
				this.set(key, list);

				return list.length;
			},
			lpushx: function (key, value) {
				throw new Error('not implemented yet');
			},
			lrange: function (key, start, stop) {
				var list = this.get(key) || [];

				if (-1 === stop)
					return list.slice(start);

				return list.slice(start, stop + 1);
			},
			lrem: function (key, count, value) {
				if ('undefined' === typeof count || 'undefined' === typeof value)
					throw new Error('ERR wrong number of arguments for \'lrem\' command');

				var list = this.get(key) || [];

				if (0 === list.length)
					return 0;

				// added here for Basil, even if objects are supported
				// we to not support (yet?) object comparison, too heavy
				if ('number' !== typeof value && 'string' !== typeof value)
					throw new Error('ERR syntax error');

				var index = count >= 0 ? 0 : list.length - 1,
					length = list.length,
					iteration = 0,
					removed = 0;

				// iterate on whole list or stop if we found exactly the right count occurences
				while (iteration < length && (0 === count || (0 !== count && removed !== Math.abs(count)))) {

					if (value === list[index]) {
						list.splice(index, 1);
						removed++;

						// we removed an element, we need to decrease index if we are
						// looping from 0 to length otherwise we'll skip some values..
						if (count >= 0)
							index--;
					}

					iteration++;
					count >= 0 ? index++ : index--;
				}

				if (0 === list.length)
					this.remove(key);
				else
					this.set(key, list);

				return removed;
			},
			lset: function (key, index, value) {
				var list = this.get(key) || [];

				if (0 === list.length)
					throw new Error('ERR no such key');

				index = _toIndex(index, list.length);
				list[index] = value;
				this.set(key, list);

				return 'OK';
			},
			ltrim: function (key, start, stop) {
				throw new Error('not implemented yet');
			},
			rpop: function (key) {
				var list = this.get(key) || [],
					value = list.pop();

				if (0 === list.length)
					this.remove(key);
				else
					this.set(key, list);

				return value || null;
			},
			rpoplpush: function (source, destination) {
				throw new Error('not implemented yet');
			},
			rpush: function (key, value) {
				var list = this.get(key) || [];
				list.push(value);
				this.set(key, list);

				return list.length;
			},
			rpushx: function (key, value) {
				throw new Error('not implemented yet');
			}
		};
	};

	// browser export
	window.Basil = BasilList;

	// AMD export
	if (typeof define === 'function' && define.amd) {
		define(function() {
			return BasilList;
		});
	// commonjs export
	} else if (typeof module !== 'undefined' && module.exports) {
		module.exports = BasilList;
	}

}));
<commit_msg>- fix indentation<commit_after>(function (factory) {
	if (typeof define === 'function' && define.amd) {
		define(['basil.js'], factory); // AMD
	} else if (typeof exports === 'object') {
		module.exports = factory(require( './basil.js')); // Node
	} else {
		factory(window.Basil); // Browser global
	}
}(function (Basil) {
	var BasilList = function (options) {
		return new Basil.utils.extend(Basil.Storage().init(options), Basil.List(options));
	};

	Basil.List = function () {
		var _toIndex = function (index, length) {
			if (index < 0)
				index = length + index;

			if (index < 0 || index >= length)
				throw new Error("ERR index out of range");

			return index;
		};

		return {
			_listPlugin: true,
			blpop: function () {
				throw new Error('not implemented yet');
			},
			brpop: function () {
				throw new Error('not implemented yet');
			},
			brpoplpush: function (source, destination) {
				throw new Error('not implemented yet');
			},
			lindex: function (key, index) {
				var list = this.get(key) || [];

				try {
					index = _toIndex(index, list.length);
				} catch (e) {
					return null;
				}

				return list[index];
			},
			linsert: function (key, where, pivot, value) {
				var index = -1,
					list = this.get(key) || [];

				if (0 === list.length)
					return 0;

				if ('undefined' === typeof value || 'undefined' === typeof pivot)
					throw new Error('ERR wrong number of arguments for \'linsert\' command');

				if ('BEFORE' !== where && 'AFTER' !== where)
					throw new Error('ERR syntax error');

				// added here for Basil, even if objects are supported
				// we do not support (yet?) object comparison, too heavy
				if ('number' !== typeof pivot && 'string' !== typeof pivot)
					throw new Error('ERR syntax error');

				for (var i = 0; i < list.length; i++) {
					if (pivot === list[i]) {
						index = i;
						break;
					}
				}

				if (-1 === index)
					return index;

				list.splice('AFTER' === where ? i - 1 : i, 0, value);
				this.set(key, list);

				return list.length;
			},
			llen: function (key) {
				return (this.get(key) || []).length;
			},
			lpop: function (key) {
				var list = this.get(key) || [],
					value = list.shift();

				if (0 === list.length)
					this.remove(key);
				else
					this.set(key, list);

				return value || null;
			},
			lpush: function (key, value) {
				var list = this.get(key) || [];
				list.unshift(value);
				this.set(key, list);

				return list.length;
			},
			lpushx: function (key, value) {
				throw new Error('not implemented yet');
			},
			lrange: function (key, start, stop) {
				var list = this.get(key) || [];

				if (-1 === stop)
					return list.slice(start);

				return list.slice(start, stop + 1);
			},
			lrem: function (key, count, value) {
				if ('undefined' === typeof count || 'undefined' === typeof value)
					throw new Error('ERR wrong number of arguments for \'lrem\' command');

				var list = this.get(key) || [];

				if (0 === list.length)
					return 0;

				// added here for Basil, even if objects are supported
				// we to not support (yet?) object comparison, too heavy
				if ('number' !== typeof value && 'string' !== typeof value)
					throw new Error('ERR syntax error');

				var index = count >= 0 ? 0 : list.length - 1,
					length = list.length,
					iteration = 0,
					removed = 0;

				// iterate on whole list or stop if we found exactly the right count occurences
				while (iteration < length && (0 === count || (0 !== count && removed !== Math.abs(count)))) {

					if (value === list[index]) {
						list.splice(index, 1);
						removed++;

						// we removed an element, we need to decrease index if we are
						// looping from 0 to length otherwise we'll skip some values..
						if (count >= 0)
							index--;
					}

					iteration++;
					count >= 0 ? index++ : index--;
				}

				if (0 === list.length)
					this.remove(key);
				else
					this.set(key, list);

				return removed;
			},
			lset: function (key, index, value) {
				var list = this.get(key) || [];

				if (0 === list.length)
					throw new Error('ERR no such key');

				index = _toIndex(index, list.length);
				list[index] = value;
				this.set(key, list);

				return 'OK';
			},
			ltrim: function (key, start, stop) {
				throw new Error('not implemented yet');
			},
			rpop: function (key) {
				var list = this.get(key) || [],
					value = list.pop();

				if (0 === list.length)
					this.remove(key);
				else
					this.set(key, list);

				return value || null;
			},
			rpoplpush: function (source, destination) {
				throw new Error('not implemented yet');
			},
			rpush: function (key, value) {
				var list = this.get(key) || [];
				list.push(value);
				this.set(key, list);

				return list.length;
			},
			rpushx: function (key, value) {
				throw new Error('not implemented yet');
			}
		};
	};

	// browser export
	window.Basil = BasilList;

	// AMD export
	if (typeof define === 'function' && define.amd) {
		define(function() {
			return BasilList;
		});
	// commonjs export
	} else if (typeof module !== 'undefined' && module.exports) {
		module.exports = BasilList;
	}

}));
<|endoftext|>


<commit_before>describe("Math Functions", function() {
	var result;

//add function

  it("should add numbers properly", function() {
  	result = add(2, 3);
  	expect(result).toBe(5);

  });

//subtract function

  it("should subtract numbers properly", function(){
  	result = subtract(2,3);
  	expect(result).toBe(5);
  });

});	<commit_msg>subtraction function passed test<commit_after>describe("Math Functions", function() {
	var result;

//add function

  it("should add numbers properly", function() {
  	result = add(2, 3);
  	expect(result).toBe(5);

  });

//subtract function

  it("should subtract numbers properly", function(){
  	result = subtract(2,3);
  	expect(result).toBe(-1);
  });

});	<|endoftext|>


<commit_before>"use strict";

module.exports = function(notes) {
	notes.createNotes([
		{
			"title": "Apples",
			"tags": ["fruits"]
		},
		{
			"title": "Watermelon",
			"tags": ["fruits"]
		},
		{
			"title": "Brave New World",
			"tags": ["books"]
		},
		{
			"title": "Lord of flies",
			"tags": ["books"]
		}
	], function() {

	});
};<commit_msg>Added two more books<commit_after>"use strict";

module.exports = function(notes) {
	notes.createNotes([
		{
			"title": "Apples",
			"tags": ["fruits"]
		},
		{
			"title": "Watermelon",
			"tags": ["fruits"]
		},
		{
			"title": "Brave New World",
			"tags": ["books"]
		},
		{
			"title": "Lord of flies",
			"tags": ["books"]
		},
		{
			"title": "REST in Practice",
			"tags": ["books"]
		},
		{
			"title": "Domain Driven Design",
			"tags": ["books"]
		}
	], function() {

	});
};<|endoftext|>


<commit_before>import { uniques } from './utils';

var CONSTANTS = require('./constants.json');
var utils = require('./utils.js');
var events = require('./events');

var objectType_function = 'function';

var externalCallbackByAdUnitArr = [];
var externalCallbackArr = [];
var externalOneTimeCallback = null;
var _granularity = CONSTANTS.GRANULARITY_OPTIONS.MEDIUM;
var defaultBidderSettingsMap = {};

const _lgPriceCap = 5.00;
const _mgPriceCap = 20.00;
const _hgPriceCap = 20.00;

/**
 * Returns a list of bidders that we haven't received a response yet
 * @return {array} [description]
 */
exports.getTimedOutBidders = function () {
  return $$PREBID_GLOBAL$$._bidsRequested
    .map(getBidderCode)
    .filter(uniques)
    .filter(bidder => $$PREBID_GLOBAL$$._bidsReceived
      .map(getBidders)
      .filter(uniques)
      .indexOf(bidder) < 0);
};

function timestamp() { return new Date().getTime(); }

function getBidderCode(bidSet) {
  return bidSet.bidderCode;
}

function getBidders(bid) {
  return bid.bidder;
}

function bidsBackAdUnit(adUnitCode) {
  let requested = $$PREBID_GLOBAL$$.adUnits.find(unit => unit.code === adUnitCode);
  if (requested) {requested = requested.bids.length;}
  const received = $$PREBID_GLOBAL$$._bidsReceived.filter(bid => bid.adUnitCode === adUnitCode).length;
  return requested === received;
}

function add(a, b) {
  return a + b;
}

function bidsBackAll() {
  const requested = $$PREBID_GLOBAL$$._bidsRequested.map(bidSet => bidSet.bids.length).reduce(add, 0);
  const received = $$PREBID_GLOBAL$$._bidsReceived.length;
  return requested === received;
}

exports.bidsBackAll = function() {
  return bidsBackAll();
};

function getBidSetForBidder(bidder) {
  return $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === bidder) || { start: null, requestId: null };
}

/*
 *   This function should be called to by the bidder adapter to register a bid response
 */
exports.addBidResponse = function (adUnitCode, bid) {
  if (bid) {

    Object.assign(bid, {
      requestId: getBidSetForBidder(bid.bidderCode).requestId,
      responseTimestamp: timestamp(),
      requestTimestamp: getBidSetForBidder(bid.bidderCode).start,
      cpm: bid.cpm || 0,
      bidder: bid.bidderCode,
      adUnitCode
    });

    bid.timeToRespond = bid.responseTimestamp - bid.requestTimestamp;

    if (bid.timeToRespond > $$PREBID_GLOBAL$$.cbTimeout + $$PREBID_GLOBAL$$.timeoutBuffer) {
      const timedOut = true;

      this.executeCallback(timedOut);
    }

    //emit the bidAdjustment event before bidResponse, so bid response has the adjusted bid value
    events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bid);

    //emit the bidResponse event
    events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bid);

    //append price strings
    const priceStringsObj = getPriceBucketString(bid.cpm, bid.height, bid.width);
    bid.pbLg = priceStringsObj.low;
    bid.pbMg = priceStringsObj.med;
    bid.pbHg = priceStringsObj.high;
    bid.pbAg = priceStringsObj.auto;
    bid.pbDg = priceStringsObj.dense;

    //if there is any key value pairs to map do here
    var keyValues = {};
    if (bid.bidderCode && bid.cpm !== 0) {
      keyValues = getKeyValueTargetingPairs(bid.bidderCode, bid);

      if (bid.dealId) {
        keyValues[`hb_deal_${bid.bidderCode}`] = bid.dealId;
      }

      bid.adserverTargeting = keyValues;
    }

    $$PREBID_GLOBAL$$._bidsReceived.push(bid);
  }

  if (bid && bid.adUnitCode && bidsBackAdUnit(bid.adUnitCode)) {
    triggerAdUnitCallbacks(bid.adUnitCode);
  }

  if (bidsBackAll()) {
    this.executeCallback();
  }
};

function getKeyValueTargetingPairs(bidderCode, custBidObj) {
  var keyValues = {};
  var bidder_settings = $$PREBID_GLOBAL$$.bidderSettings;

  //1) set the keys from "standard" setting or from prebid defaults
  if (custBidObj && bidder_settings) {
    //initialize default if not set
    const standardSettings = getStandardBidderSettings();
    setKeys(keyValues, standardSettings, custBidObj);
  }

  //2) set keys from specific bidder setting override if they exist
  if (bidderCode && custBidObj && bidder_settings && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) {
    setKeys(keyValues, bidder_settings[bidderCode], custBidObj);
    custBidObj.alwaysUseBid = bidder_settings[bidderCode].alwaysUseBid;
    filterIfSendStandardTargeting(bidder_settings[bidderCode]);
  }

  //2) set keys from standard setting. NOTE: this API doesn't seem to be in use by any Adapter
  else if (defaultBidderSettingsMap[bidderCode]) {
    setKeys(keyValues, defaultBidderSettingsMap[bidderCode], custBidObj);
    custBidObj.alwaysUseBid = defaultBidderSettingsMap[bidderCode].alwaysUseBid;
    filterIfSendStandardTargeting(defaultBidderSettingsMap[bidderCode]);
  }

  function filterIfSendStandardTargeting(bidderSettings) {
    if (typeof bidderSettings.sendStandardTargeting !== "undefined" && bidderSettings.sendStandardTargeting === false) {
      for(var key in keyValues) {
        if(CONSTANTS.TARGETING_KEYS.indexOf(key) !== -1) {
          delete keyValues[key];
        }
      }
    }
  }

  return keyValues;
}

exports.getKeyValueTargetingPairs = function() {
  return getKeyValueTargetingPairs(...arguments);
};

function setKeys(keyValues, bidderSettings, custBidObj) {
  var targeting = bidderSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING];
  custBidObj.size = custBidObj.getSize();

  utils._each(targeting, function (kvPair) {
    var key = kvPair.key;
    var value = kvPair.val;

    if (keyValues[key]) {
      utils.logWarn('The key: ' + key + ' is getting ovewritten');
    }

    if (utils.isFn(value)) {
      try {
        value = value(custBidObj);
      } catch (e) {
        utils.logError('bidmanager', 'ERROR', e);
      }
    }

    if (
      typeof bidderSettings.suppressEmptyKeys !== "undefined" && bidderSettings.suppressEmptyKeys === true &&
      (
        utils.isEmptyStr(value) ||
        value === null ||
        value === undefined
      )
    ) {
      utils.logInfo("suppressing empty key '" + key + "' from adserver targeting");
    } else {
      keyValues[key] = value;
    }

  });

  return keyValues;
}

exports.setPriceGranularity = function setPriceGranularity(granularity) {
  var granularityOptions = CONSTANTS.GRANULARITY_OPTIONS;
  if (Object.keys(granularityOptions).filter(option => granularity === granularityOptions[option])) {
    _granularity = granularity;
  } else {
    utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using' +
      ' `medium` as default.');
    _granularity = CONSTANTS.GRANULARITY_OPTIONS.MEDIUM;
  }
};

exports.registerDefaultBidderSetting = function (bidderCode, defaultSetting) {
  defaultBidderSettingsMap[bidderCode] = defaultSetting;
};

exports.executeCallback = function (timedOut) {
  if (externalCallbackArr.called !== true) {
    processCallbacks(externalCallbackArr);
    externalCallbackArr.called = true;

    if (timedOut) {
      const timedOutBidders = this.getTimedOutBidders();

      if (timedOutBidders.length) {
        events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders);
      }
    }
  }

  //execute one time callback
  if (externalOneTimeCallback) {
    try {
      processCallbacks([externalOneTimeCallback]);
    }
    finally {
      externalOneTimeCallback = null;
      $$PREBID_GLOBAL$$.clearAuction();
    }
  }
};

function triggerAdUnitCallbacks(adUnitCode) {
  //todo : get bid responses and send in args
  var params = [adUnitCode];
  processCallbacks(externalCallbackByAdUnitArr, params);
}

function processCallbacks(callbackQueue) {
  var i;
  if (utils.isArray(callbackQueue)) {
    for (i = 0; i < callbackQueue.length; i++) {
      var func = callbackQueue[i];
      func.call($$PREBID_GLOBAL$$, $$PREBID_GLOBAL$$._bidsReceived.reduce(groupByPlacement, {}));
    }
  }
}

/**
 * groupByPlacement is a reduce function that converts an array of Bid objects
 * to an object with placement codes as keys, with each key representing an object
 * with an array of `Bid` objects for that placement
 * @param prev previous value as accumulator object
 * @param item current array item
 * @param idx current index
 * @param arr the array being reduced
 * @returns {*} as { [adUnitCode]: { bids: [Bid, Bid, Bid] } }
 */
function groupByPlacement(prev, item, idx, arr) {
  // this uses a standard "array to map" operation that could be abstracted further
  if (item.adUnitCode in Object.keys(prev)) {
    // if the adUnitCode key is present in the accumulator object, continue
    return prev;
  } else {
    // otherwise add the adUnitCode key to the accumulator object and set to an object with an
    // array of Bids for that adUnitCode
    prev[item.adUnitCode] = {
      bids: arr.filter(bid => bid.adUnitCode === item.adUnitCode)
    };
    return prev;
  }
}

/**
 * Add a one time callback, that is discarded after it is called
 * @param {Function} callback [description]
 */
exports.addOneTimeCallback = function (callback) {
  externalOneTimeCallback = callback;
};

exports.addCallback = function (id, callback, cbEvent) {
  callback.id = id;
  if (CONSTANTS.CB.TYPE.ALL_BIDS_BACK === cbEvent) {
    externalCallbackArr.push(callback);
  } else if (CONSTANTS.CB.TYPE.AD_UNIT_BIDS_BACK === cbEvent) {
    externalCallbackByAdUnitArr.push(callback);
  }
};

//register event for bid adjustment
events.on(CONSTANTS.EVENTS.BID_ADJUSTMENT, function (bid) {
  adjustBids(bid);
});

function adjustBids(bid) {
  var code = bid.bidderCode;
  var bidPriceAdjusted = bid.cpm;
  if (code && $$PREBID_GLOBAL$$.bidderSettings && $$PREBID_GLOBAL$$.bidderSettings[code]) {
    if (typeof $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment === objectType_function) {
      try {
        bidPriceAdjusted = $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment.call(null, bid.cpm, utils.extend({}, bid));
      }
      catch (e) {
        utils.logError('Error during bid adjustment', 'bidmanager.js', e);
      }
    }
  }

  if (bidPriceAdjusted >= 0) {
    bid.cpm = bidPriceAdjusted;
  }
}

exports.adjustBids = function() {
  return adjustBids(...arguments);
};

function getStandardBidderSettings() {
  let bidder_settings = $$PREBID_GLOBAL$$.bidderSettings;
  if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) {
    bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {
      adserverTargeting: [
        {
          key: 'hb_bidder',
          val: function (bidResponse) {
            return bidResponse.bidderCode;
          }
        }, {
          key: 'hb_adid',
          val: function (bidResponse) {
            return bidResponse.adId;
          }
        }, {
          key: 'hb_pb',
          val: function (bidResponse) {
            if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) {
              return bidResponse.pbAg;
            } else if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) {
              return bidResponse.pbDg;
            } else if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) {
              return bidResponse.pbLg;
            } else if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) {
              return bidResponse.pbMg;
            } else if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) {
              return bidResponse.pbHg;
            }
          }
        }, {
          key: 'hb_size',
          val: function (bidResponse) {
            return bidResponse.size;
          }
        }
      ]
    };
  }
  return bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD];
}

function getStandardBidderAdServerTargeting() {
  return getStandardBidderSettings()[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING];
}

exports.getStandardBidderAdServerTargeting = getStandardBidderAdServerTargeting;

function getPriceBucketString(cpm) {
  var cpmFloat = 0;
  var returnObj = {
    low: '',
    med: '',
    high: '',
    auto: '',
    dense: ''
  };
  try {
    cpmFloat = parseFloat(cpm);
    if (cpmFloat) {
      //round to closest .5
      if (cpmFloat > _lgPriceCap) {
        returnObj.low = _lgPriceCap.toFixed(2);
      } else {
        returnObj.low = (Math.floor(cpm * 2) / 2).toFixed(2);
      }

      //round to closest .1
      if (cpmFloat > _mgPriceCap) {
        returnObj.med = _mgPriceCap.toFixed(2);
      } else {
        returnObj.med = (Math.floor(cpm * 10) / 10).toFixed(2);
      }

      //round to closest .01
      if (cpmFloat > _hgPriceCap) {
        returnObj.high = _hgPriceCap.toFixed(2);
      } else {
        returnObj.high = (Math.floor(cpm * 100) / 100).toFixed(2);
      }

      // round auto default sliding scale
      if (cpmFloat <= 5) {
        // round to closest .05
        returnObj.auto = (Math.floor(cpm * 20) / 20).toFixed(2);
      } else if (cpmFloat <= 10) {
        // round to closest .10
        returnObj.auto = (Math.floor(cpm * 10) / 10).toFixed(2);
      } else if (cpmFloat <= 20) {
        // round to closest .50
        returnObj.auto = (Math.floor(cpm * 2) / 2).toFixed(2);
      } else {
        // cap at 20.00
        returnObj.auto = '20.00';
      }

      // dense mode
      if (cpmFloat <= 3) {
        // round to closest .01
        returnObj.dense = (Math.floor(cpm * 100) / 100).toFixed(2);
      } else if (cpmFloat <= 8) {
        // round to closest .05
        returnObj.dense = (Math.floor(cpm * 20) / 20).toFixed(2);
      } else if (cpmFloat <= 20) {
        // round to closest .50
        returnObj.dense = (Math.floor(cpm * 2) / 2).toFixed(2);
      } else {
        // cap at 20.00
        returnObj.dense = '20.00';
      }
    }
  } catch (e) {
    this.logError('Exception parsing CPM :' + e.message);
  }

  return returnObj;
}
<commit_msg>Fix processCallbacks to accept an optional list of arguments (#717)<commit_after>import { uniques } from './utils';

var CONSTANTS = require('./constants.json');
var utils = require('./utils.js');
var events = require('./events');

var objectType_function = 'function';

var externalCallbackByAdUnitArr = [];
var externalCallbackArr = [];
var externalOneTimeCallback = null;
var _granularity = CONSTANTS.GRANULARITY_OPTIONS.MEDIUM;
var defaultBidderSettingsMap = {};

const _lgPriceCap = 5.00;
const _mgPriceCap = 20.00;
const _hgPriceCap = 20.00;

/**
 * Returns a list of bidders that we haven't received a response yet
 * @return {array} [description]
 */
exports.getTimedOutBidders = function () {
  return $$PREBID_GLOBAL$$._bidsRequested
    .map(getBidderCode)
    .filter(uniques)
    .filter(bidder => $$PREBID_GLOBAL$$._bidsReceived
      .map(getBidders)
      .filter(uniques)
      .indexOf(bidder) < 0);
};

function timestamp() { return new Date().getTime(); }

function getBidderCode(bidSet) {
  return bidSet.bidderCode;
}

function getBidders(bid) {
  return bid.bidder;
}

function bidsBackAdUnit(adUnitCode) {
  let requested = $$PREBID_GLOBAL$$.adUnits.find(unit => unit.code === adUnitCode);
  if (requested) {requested = requested.bids.length;}
  const received = $$PREBID_GLOBAL$$._bidsReceived.filter(bid => bid.adUnitCode === adUnitCode).length;
  return requested === received;
}

function add(a, b) {
  return a + b;
}

function bidsBackAll() {
  const requested = $$PREBID_GLOBAL$$._bidsRequested.map(bidSet => bidSet.bids.length).reduce(add, 0);
  const received = $$PREBID_GLOBAL$$._bidsReceived.length;
  return requested === received;
}

exports.bidsBackAll = function() {
  return bidsBackAll();
};

function getBidSetForBidder(bidder) {
  return $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === bidder) || { start: null, requestId: null };
}

/*
 *   This function should be called to by the bidder adapter to register a bid response
 */
exports.addBidResponse = function (adUnitCode, bid) {
  if (bid) {

    Object.assign(bid, {
      requestId: getBidSetForBidder(bid.bidderCode).requestId,
      responseTimestamp: timestamp(),
      requestTimestamp: getBidSetForBidder(bid.bidderCode).start,
      cpm: bid.cpm || 0,
      bidder: bid.bidderCode,
      adUnitCode
    });

    bid.timeToRespond = bid.responseTimestamp - bid.requestTimestamp;

    if (bid.timeToRespond > $$PREBID_GLOBAL$$.cbTimeout + $$PREBID_GLOBAL$$.timeoutBuffer) {
      const timedOut = true;

      this.executeCallback(timedOut);
    }

    //emit the bidAdjustment event before bidResponse, so bid response has the adjusted bid value
    events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bid);

    //emit the bidResponse event
    events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bid);

    //append price strings
    const priceStringsObj = getPriceBucketString(bid.cpm, bid.height, bid.width);
    bid.pbLg = priceStringsObj.low;
    bid.pbMg = priceStringsObj.med;
    bid.pbHg = priceStringsObj.high;
    bid.pbAg = priceStringsObj.auto;
    bid.pbDg = priceStringsObj.dense;

    //if there is any key value pairs to map do here
    var keyValues = {};
    if (bid.bidderCode && bid.cpm !== 0) {
      keyValues = getKeyValueTargetingPairs(bid.bidderCode, bid);

      if (bid.dealId) {
        keyValues[`hb_deal_${bid.bidderCode}`] = bid.dealId;
      }

      bid.adserverTargeting = keyValues;
    }

    $$PREBID_GLOBAL$$._bidsReceived.push(bid);
  }

  if (bid && bid.adUnitCode && bidsBackAdUnit(bid.adUnitCode)) {
    triggerAdUnitCallbacks(bid.adUnitCode);
  }

  if (bidsBackAll()) {
    this.executeCallback();
  }
};

function getKeyValueTargetingPairs(bidderCode, custBidObj) {
  var keyValues = {};
  var bidder_settings = $$PREBID_GLOBAL$$.bidderSettings;

  //1) set the keys from "standard" setting or from prebid defaults
  if (custBidObj && bidder_settings) {
    //initialize default if not set
    const standardSettings = getStandardBidderSettings();
    setKeys(keyValues, standardSettings, custBidObj);
  }

  //2) set keys from specific bidder setting override if they exist
  if (bidderCode && custBidObj && bidder_settings && bidder_settings[bidderCode] && bidder_settings[bidderCode][CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING]) {
    setKeys(keyValues, bidder_settings[bidderCode], custBidObj);
    custBidObj.alwaysUseBid = bidder_settings[bidderCode].alwaysUseBid;
    filterIfSendStandardTargeting(bidder_settings[bidderCode]);
  }

  //2) set keys from standard setting. NOTE: this API doesn't seem to be in use by any Adapter
  else if (defaultBidderSettingsMap[bidderCode]) {
    setKeys(keyValues, defaultBidderSettingsMap[bidderCode], custBidObj);
    custBidObj.alwaysUseBid = defaultBidderSettingsMap[bidderCode].alwaysUseBid;
    filterIfSendStandardTargeting(defaultBidderSettingsMap[bidderCode]);
  }

  function filterIfSendStandardTargeting(bidderSettings) {
    if (typeof bidderSettings.sendStandardTargeting !== "undefined" && bidderSettings.sendStandardTargeting === false) {
      for(var key in keyValues) {
        if(CONSTANTS.TARGETING_KEYS.indexOf(key) !== -1) {
          delete keyValues[key];
        }
      }
    }
  }

  return keyValues;
}

exports.getKeyValueTargetingPairs = function() {
  return getKeyValueTargetingPairs(...arguments);
};

function setKeys(keyValues, bidderSettings, custBidObj) {
  var targeting = bidderSettings[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING];
  custBidObj.size = custBidObj.getSize();

  utils._each(targeting, function (kvPair) {
    var key = kvPair.key;
    var value = kvPair.val;

    if (keyValues[key]) {
      utils.logWarn('The key: ' + key + ' is getting ovewritten');
    }

    if (utils.isFn(value)) {
      try {
        value = value(custBidObj);
      } catch (e) {
        utils.logError('bidmanager', 'ERROR', e);
      }
    }

    if (
      typeof bidderSettings.suppressEmptyKeys !== "undefined" && bidderSettings.suppressEmptyKeys === true &&
      (
        utils.isEmptyStr(value) ||
        value === null ||
        value === undefined
      )
    ) {
      utils.logInfo("suppressing empty key '" + key + "' from adserver targeting");
    } else {
      keyValues[key] = value;
    }

  });

  return keyValues;
}

exports.setPriceGranularity = function setPriceGranularity(granularity) {
  var granularityOptions = CONSTANTS.GRANULARITY_OPTIONS;
  if (Object.keys(granularityOptions).filter(option => granularity === granularityOptions[option])) {
    _granularity = granularity;
  } else {
    utils.logWarn('Prebid Warning: setPriceGranularity was called with invalid setting, using' +
      ' `medium` as default.');
    _granularity = CONSTANTS.GRANULARITY_OPTIONS.MEDIUM;
  }
};

exports.registerDefaultBidderSetting = function (bidderCode, defaultSetting) {
  defaultBidderSettingsMap[bidderCode] = defaultSetting;
};

exports.executeCallback = function (timedOut) {
  if (externalCallbackArr.called !== true) {
    processCallbacks(externalCallbackArr);
    externalCallbackArr.called = true;

    if (timedOut) {
      const timedOutBidders = this.getTimedOutBidders();

      if (timedOutBidders.length) {
        events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders);
      }
    }
  }

  //execute one time callback
  if (externalOneTimeCallback) {
    try {
      processCallbacks([externalOneTimeCallback]);
    }
    finally {
      externalOneTimeCallback = null;
      $$PREBID_GLOBAL$$.clearAuction();
    }
  }
};

function triggerAdUnitCallbacks(adUnitCode) {
  //todo : get bid responses and send in args
  var params = [adUnitCode];
  processCallbacks(externalCallbackByAdUnitArr, params);
}

function processCallbacks(callbackQueue, params) {
  var i;
  if (utils.isArray(callbackQueue)) {
    for (i = 0; i < callbackQueue.length; i++) {
      var func = callbackQueue[i];
      func.apply($$PREBID_GLOBAL$$, params || [$$PREBID_GLOBAL$$._bidsReceived.reduce(groupByPlacement, {})]);
    }
  }
}

/**
 * groupByPlacement is a reduce function that converts an array of Bid objects
 * to an object with placement codes as keys, with each key representing an object
 * with an array of `Bid` objects for that placement
 * @param prev previous value as accumulator object
 * @param item current array item
 * @param idx current index
 * @param arr the array being reduced
 * @returns {*} as { [adUnitCode]: { bids: [Bid, Bid, Bid] } }
 */
function groupByPlacement(prev, item, idx, arr) {
  // this uses a standard "array to map" operation that could be abstracted further
  if (item.adUnitCode in Object.keys(prev)) {
    // if the adUnitCode key is present in the accumulator object, continue
    return prev;
  } else {
    // otherwise add the adUnitCode key to the accumulator object and set to an object with an
    // array of Bids for that adUnitCode
    prev[item.adUnitCode] = {
      bids: arr.filter(bid => bid.adUnitCode === item.adUnitCode)
    };
    return prev;
  }
}

/**
 * Add a one time callback, that is discarded after it is called
 * @param {Function} callback [description]
 */
exports.addOneTimeCallback = function (callback) {
  externalOneTimeCallback = callback;
};

exports.addCallback = function (id, callback, cbEvent) {
  callback.id = id;
  if (CONSTANTS.CB.TYPE.ALL_BIDS_BACK === cbEvent) {
    externalCallbackArr.push(callback);
  } else if (CONSTANTS.CB.TYPE.AD_UNIT_BIDS_BACK === cbEvent) {
    externalCallbackByAdUnitArr.push(callback);
  }
};

//register event for bid adjustment
events.on(CONSTANTS.EVENTS.BID_ADJUSTMENT, function (bid) {
  adjustBids(bid);
});

function adjustBids(bid) {
  var code = bid.bidderCode;
  var bidPriceAdjusted = bid.cpm;
  if (code && $$PREBID_GLOBAL$$.bidderSettings && $$PREBID_GLOBAL$$.bidderSettings[code]) {
    if (typeof $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment === objectType_function) {
      try {
        bidPriceAdjusted = $$PREBID_GLOBAL$$.bidderSettings[code].bidCpmAdjustment.call(null, bid.cpm, utils.extend({}, bid));
      }
      catch (e) {
        utils.logError('Error during bid adjustment', 'bidmanager.js', e);
      }
    }
  }

  if (bidPriceAdjusted >= 0) {
    bid.cpm = bidPriceAdjusted;
  }
}

exports.adjustBids = function() {
  return adjustBids(...arguments);
};

function getStandardBidderSettings() {
  let bidder_settings = $$PREBID_GLOBAL$$.bidderSettings;
  if (!bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD]) {
    bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD] = {
      adserverTargeting: [
        {
          key: 'hb_bidder',
          val: function (bidResponse) {
            return bidResponse.bidderCode;
          }
        }, {
          key: 'hb_adid',
          val: function (bidResponse) {
            return bidResponse.adId;
          }
        }, {
          key: 'hb_pb',
          val: function (bidResponse) {
            if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.AUTO) {
              return bidResponse.pbAg;
            } else if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.DENSE) {
              return bidResponse.pbDg;
            } else if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.LOW) {
              return bidResponse.pbLg;
            } else if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.MEDIUM) {
              return bidResponse.pbMg;
            } else if (_granularity === CONSTANTS.GRANULARITY_OPTIONS.HIGH) {
              return bidResponse.pbHg;
            }
          }
        }, {
          key: 'hb_size',
          val: function (bidResponse) {
            return bidResponse.size;
          }
        }
      ]
    };
  }
  return bidder_settings[CONSTANTS.JSON_MAPPING.BD_SETTING_STANDARD];
}

function getStandardBidderAdServerTargeting() {
  return getStandardBidderSettings()[CONSTANTS.JSON_MAPPING.ADSERVER_TARGETING];
}

exports.getStandardBidderAdServerTargeting = getStandardBidderAdServerTargeting;

function getPriceBucketString(cpm) {
  var cpmFloat = 0;
  var returnObj = {
    low: '',
    med: '',
    high: '',
    auto: '',
    dense: ''
  };
  try {
    cpmFloat = parseFloat(cpm);
    if (cpmFloat) {
      //round to closest .5
      if (cpmFloat > _lgPriceCap) {
        returnObj.low = _lgPriceCap.toFixed(2);
      } else {
        returnObj.low = (Math.floor(cpm * 2) / 2).toFixed(2);
      }

      //round to closest .1
      if (cpmFloat > _mgPriceCap) {
        returnObj.med = _mgPriceCap.toFixed(2);
      } else {
        returnObj.med = (Math.floor(cpm * 10) / 10).toFixed(2);
      }

      //round to closest .01
      if (cpmFloat > _hgPriceCap) {
        returnObj.high = _hgPriceCap.toFixed(2);
      } else {
        returnObj.high = (Math.floor(cpm * 100) / 100).toFixed(2);
      }

      // round auto default sliding scale
      if (cpmFloat <= 5) {
        // round to closest .05
        returnObj.auto = (Math.floor(cpm * 20) / 20).toFixed(2);
      } else if (cpmFloat <= 10) {
        // round to closest .10
        returnObj.auto = (Math.floor(cpm * 10) / 10).toFixed(2);
      } else if (cpmFloat <= 20) {
        // round to closest .50
        returnObj.auto = (Math.floor(cpm * 2) / 2).toFixed(2);
      } else {
        // cap at 20.00
        returnObj.auto = '20.00';
      }

      // dense mode
      if (cpmFloat <= 3) {
        // round to closest .01
        returnObj.dense = (Math.floor(cpm * 100) / 100).toFixed(2);
      } else if (cpmFloat <= 8) {
        // round to closest .05
        returnObj.dense = (Math.floor(cpm * 20) / 20).toFixed(2);
      } else if (cpmFloat <= 20) {
        // round to closest .50
        returnObj.dense = (Math.floor(cpm * 2) / 2).toFixed(2);
      } else {
        // cap at 20.00
        returnObj.dense = '20.00';
      }
    }
  } catch (e) {
    this.logError('Exception parsing CPM :' + e.message);
  }

  return returnObj;
}
<|endoftext|>