<commit_before>var path  = require('path');
var async = require('async');
var Utils = require('../../../Utils');
var Store = require('../../../Store');

exports.definition = {
  mixinCallback: function(){
    var store = this.store;

    this.use(function(next){

      if(!store.migrations_running){
        store.runMigrations();
      }

      //put that one after loadMigrations to finish the middleware without any async stuff if there is no connection - or migration
      if(store.migrations_finished){
        return next();
      }

      store.once('migrations_finished', next);

    }, 100);
  }
};

exports.store = {
  mixinCallback: function(){
    this.migration_table = this.config.migration_table || 'openrecord_migrations';
    this.migrations = [];

    if(this.config.migrations && typeof this.config.migrations == 'string'){
      this.loadMigrations(this.config.migrations);
    }
  },

  Migration: function(name, fn){
    this.migrations.push({name:name, fn:fn});
  },

  loadMigrations: function(loadpath){
    var migrations = Utils.require(loadpath, {includePathNames: true});

    for(var fullpath in migrations){
      if(migrations.hasOwnProperty(fullpath) && typeof migrations[fullpath] == 'function'){
        var migration_name = path.basename(fullpath, path.extname(fullpath));

        this.Migration(migration_name, migrations[fullpath]);
      }
    }
  },

  runMigrations: function(){
    this.migrations_running = true;

    if(!this.connection || this.migrations.length == 0){
      this.migrations_finished = true;
      this.migrations_running = false;
      return;
    }

    var self = this;
    this.loadMigrationHistory(function(finished_migrations){
      self.runMissingMigrations(finished_migrations, function(){
        self.migrations_finished = true;
        self.migrations_running = false;
        self.emit('migrations_finished');
      });
    });
  },

  loadMigrationHistory: function(callback){
    var self = this;

    this.connection.schema.hasTable(this.migration_table).then(function(exists){
      if(exists){

        self.connection(self.migration_table).then(function(result){
          var names = [];

          for(var i = 0; i < result.length; i++){
            names.push(result[i].name);
          }

          callback(names);
        });
      }else{
        self.connection.schema.createTable(self.migration_table, function(table){
          table.string('name');
        }).then(function(){
          callback([]);
        });
      }
    });
  },

  runMissingMigrations: function(finished_migrations, callback){
    var missing = [];

    var Migration = {connection: this.connection, store: this};
    Utils.mixin(Migration, Store.registeredTypes[this.type], {only: 'migration'});
    Utils.mixinCallbacks(Migration, {});

    //Migrations are handled in series
    //First the migration method will be called
    //for every operation a new queue item will be added
    //after that, we'll execute the queue
    for(var i = 0; i < this.migrations.length; i++){
      if(finished_migrations.indexOf(this.migrations[i].name) == -1){
        (function(fn){
          missing.push(function(done){
            var queue = [];
            Migration.queue = queue;

            try{

              Migration.startTransaction();
              fn.call(Migration);
              Migration.commit();

              //Run the operation queue
              async.series(queue, done);
            }catch(e){
              done(e);
            }

          });
        })(this.migrations[i].fn);
      }
    }

    async.series(missing, function(err){
      if(err){
        Migration.rollback();
        console.log('ROLLBACK', err);
      }
      callback();
    });

  }

};<commit_msg>save finished migrations in the db<commit_after>var path  = require('path');
var async = require('async');
var Utils = require('../../../Utils');
var Store = require('../../../Store');

exports.definition = {
  mixinCallback: function(){
    var store = this.store;

    this.use(function(next){

      if(!store.migrations_running){
        store.runMigrations();
      }

      //put that one after loadMigrations to finish the middleware without any async stuff if there is no connection - or migration
      if(store.migrations_finished){
        return next();
      }

      store.once('migrations_finished', next);

    }, 100);
  }
};

exports.store = {
  mixinCallback: function(){
    this.migration_table = this.config.migration_table || 'openrecord_migrations';
    this.migrations = [];

    if(this.config.migrations && typeof this.config.migrations == 'string'){
      this.loadMigrations(this.config.migrations);
    }
  },

  Migration: function(name, fn){
    this.migrations.push({name:name, fn:fn});
  },

  loadMigrations: function(loadpath){
    var migrations = Utils.require(loadpath, {includePathNames: true});

    for(var fullpath in migrations){
      if(migrations.hasOwnProperty(fullpath) && typeof migrations[fullpath] == 'function'){
        var migration_name = path.basename(fullpath, path.extname(fullpath));

        this.Migration(migration_name, migrations[fullpath]);
      }
    }
  },

  runMigrations: function(){
    this.migrations_running = true;

    if(!this.connection || this.migrations.length == 0){
      this.migrations_finished = true;
      this.migrations_running = false;
      return;
    }

    var self = this;
    this.loadMigrationHistory(function(finished_migrations){
      self.runMissingMigrations(finished_migrations, function(){
        self.migrations_finished = true;
        self.migrations_running = false;
        self.emit('migrations_finished');
      });
    });
  },

  loadMigrationHistory: function(callback){
    var self = this;

    this.connection.schema.hasTable(this.migration_table).then(function(exists){
      if(exists){

        self.connection(self.migration_table).then(function(result){
          var names = [];

          for(var i = 0; i < result.length; i++){
            names.push(result[i].name);
          }

          callback(names);
        });
      }else{
        self.connection.schema.createTable(self.migration_table, function(table){
          table.string('name');
        }).then(function(){
          callback([]);
        });
      }
    });
  },

  runMissingMigrations: function(finished_migrations, callback){
    var missing = [];
    var self = this;

    var Migration = {connection: this.connection, store: this};
    Utils.mixin(Migration, Store.registeredTypes[this.type], {only: 'migration'});
    Utils.mixinCallbacks(Migration, {});

    //Migrations are handled in series
    //First the migration method will be called
    //for every operation a new queue item will be added
    //after that, we'll execute the queue
    for(var i = 0; i < this.migrations.length; i++){
      if(finished_migrations.indexOf(this.migrations[i].name) == -1){
        (function(fn, name){
          missing.push(function(done){
            var queue = [];
            Migration.queue = queue;

            try{

              Migration.startTransaction();
              fn.call(Migration);
              Migration.commit();

              //Run the operation queue
              async.series(queue, function(err){
                if(err) return done(err);
                self.connection(self.migration_table).insert({name:name}).then(function(){
                  done();
                }, function(err){
                  done(err);
                });

              });
            }catch(e){
              done(e);
            }

          });
        })(this.migrations[i].fn, this.migrations[i].name);
      }
    }

    async.series(missing, function(err){
      if(err){
        Migration.rollback();
        console.log('ROLLBACK', err);
      }
      callback();
    });

  }

};<|endoftext|>


<commit_before>'use strict';

function mousedownListener(e) {
    let mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) -
        this.canvas.offsetLeft;
    let mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) -
        this.canvas.offsetTop;
    this.paint = true;
    this.addClick(mouseX, mouseY, '#1a7fcc');
    this.redraw();
}

function mousemoveListener(e) {
    let mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) -
        this.canvas.offsetLeft;
    let mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) -
        this.canvas.offsetTop;
    if (this.paint) {
        this.addClick(mouseX, mouseY, '#1a7fcc', true);
        this.redraw();
    }
    // Prevent the whole page from dragging if on mobile
    e.preventDefault();
}

function mouseupListener() {
    this.paint = false;
}

function setEventListeners() {
    this.canvas.addEventListener(
        'mousedown', mousedownListener.bind(this), false
    );
    this.canvas.addEventListener(
        'mouseup', mouseupListener.bind(this), false
    );
    this.canvas.addEventListener(
        'mousemove', mousemoveListener.bind(this), false
    );
    this.canvas.addEventListener(
        'touchstart', mousedownListener.bind(this), false
    );
    this.canvas.addEventListener(
        'touchmove', mousemoveListener.bind(this), false
    );
    this.canvas.addEventListener(
        'touchend', mouseupListener.bind(this), false
    );
}

let DrawingCanvas = function(divId) {
    this.canvasDiv = document.getElementById(divId);
    this.canvas = document.createElement('canvas');
    this.canvas.setAttribute('width', '300');
    this.canvas.setAttribute('height', '600');
    this.canvas.setAttribute('class', 'DrawingCanvas');
    this.canvasDiv.appendChild(this.canvas);
    this.paint = false;
    setEventListeners.apply(this);
    this.context = this.canvas.getContext('2d');
    this.clickX = [];
    this.clickY = [];
    this.clickDrag = [];
    this.clickColor = [];
};

DrawingCanvas.prototype.addClick = function(x, y, color, dragging = false) {
    this.clickX.push(x);
    this.clickY.push(y);
    this.clickDrag.push(dragging);
    this.clickColor.push(color);
};

DrawingCanvas.prototype.redraw = function() {
    this.context.clearRect(
        0, 0, this.context.canvas.width, this.context.canvas.height
    );

    this.context.lineJoin = 'round';
    this.context.lineWidth = 5;

    for (let i = 0; i < this.clickX.length; i++) {
        this.context.beginPath();
        this.context.strokeStyle = this.clickColor[i];
        if (this.clickDrag[i] && i) {
            this.context.moveTo(this.clickX[i-1], this.clickY[i-1]);
        } else {
            this.context.moveTo(this.clickX[i] - 1, this.clickY[i]);
        }
        this.context.lineTo(this.clickX[i], this.clickY[i]);
        this.context.closePath();
        this.context.stroke();
    }
};

module.exports = DrawingCanvas;
<commit_msg>try to add same changes as before<commit_after>'use strict';

function mousedownListener(e) {
    let mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) -
        this.canvas.offsetLeft;
    let mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) -
        this.canvas.offsetTop;
    this.paint = true;
    this.addClick(mouseX, mouseY, '#1a7fcc');
    this.redraw();
}

function mousemoveListener(e) {
    let mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) -
        this.canvas.offsetLeft;
    let mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) -
        this.canvas.offsetTop;
    if (this.paint) {
        this.addClick(mouseX, mouseY, '#1a7fcc', true);
        this.redraw();
    }
    // Prevent the whole page from dragging if on mobile
    e.preventDefault();
}

function mouseupListener() {
    this.paint = false;
}

function setEventListeners() {
    this.canvas.addEventListener(
        'mousedown', mousedownListener.bind(this), false
    );
    this.canvas.addEventListener(
        'mouseup', mouseupListener.bind(this), false
    );
    this.canvas.addEventListener(
        'mousemove', mousemoveListener.bind(this), false
    );
    this.canvas.addEventListener(
        'touchstart', mousedownListener.bind(this), false
    );
    this.canvas.addEventListener(
        'touchmove', mousemoveListener.bind(this), false
    );
    this.canvas.addEventListener(
        'touchend', mouseupListener.bind(this), false
    );
}

let DrawingCanvas = function(divId) {
    this.stylingOptions = {
      colour: '#cb3594',
      width: 8,
      type: 'pen'
    };
    this.canvasDiv = document.getElementById(divId);
    this.canvas = document.createElement('canvas');
    this.canvas.setAttribute('width', '300');
    this.canvas.setAttribute('height', '600');
    this.canvas.setAttribute('class', 'DrawingCanvas');
    this.canvasDiv.appendChild(this.canvas);
    this.paint = false;
    setEventListeners.apply(this);
    this.context = this.canvas.getContext('2d');
    this.clickX = [];
    this.clickY = [];
    this.clickDrag = [];
    this.clickColor = [];
<<<<<<< bf80e1b454014d9dab8b27f4b21ce83024b7a90f
};
=======
    this.clickSize = [];
}
>>>>>>> try to make styling as an object of the canvas function

DrawingCanvas.prototype.addClick = function(x, y, color, dragging = false) {
    this.clickX.push(x);
    this.clickY.push(y);
    this.clickDrag.push(dragging);
    this.clickColor.push(color);
};

DrawingCanvas.prototype.redraw = function() {
    this.context.clearRect(
        0, 0, this.context.canvas.width, this.context.canvas.height
    );

    this.context.lineJoin = 'round';
    this.context.lineWidth = 5;

    for (let i = 0; i < this.clickX.length; i++) {
        this.context.beginPath();
        this.context.strokeStyle = this.clickColor[i];
        if (this.clickDrag[i] && i) {
            this.context.moveTo(this.clickX[i-1], this.clickY[i-1]);
        } else {
            this.context.moveTo(this.clickX[i] - 1, this.clickY[i]);
        }
        this.context.lineTo(this.clickX[i], this.clickY[i]);
        this.context.closePath();
        this.context.stroke();
    }
};

module.exports = DrawingCanvas;
<|endoftext|>


<commit_before>var detect = require('feature-detect-es6')

module.exports = detect.class() && detect.arrowFunction()
  ? require('./lib/command-line-args')
  : require('./lib/es5-compiled')
<commit_msg>fix index<commit_after>var detect = require('feature-detect-es6')

module.exports = detect.class() && detect.arrowFunction()
  ? require('./lib/command-line-args')
  : require('./es5/command-line-args')
<|endoftext|>


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

'use strict';

const yargs = require('yargs');
const semver = require('semver');
const Printer = require('./printer');
const lighthouse = require('../lighthouse-core');

// node 5.x required due to use of ES2015 features
if (semver.lt(process.version, '5.0.0')) {
  console.error('Lighthouse requires node version 5.0 or newer');
  process.exit(1);
}

const cli = yargs
  .help('help')
  .version()
  .showHelpOnFail(false, 'Specify --help for available options')

  .usage('$0 url')

  // List of options
  .group([
    'verbose',
    'quiet'
  ], 'Logging:')
  .describe({
    verbose: 'Displays verbose logging',
    quiet: 'Displays no progress or debug logs'
  })

  .group([
    'mobile',
    'load-page',
    'save-assets',
    'save-artifacts',
    'audit-whitelist',
    'list-all-audits',
    'list-trace-categories',
    'config-path'
  ], 'Configuration:')
  .describe({
    'mobile': 'Emulates a Nexus 5X',
    'load-page': 'Loads the page',
    'save-assets': 'Save the trace contents & screenshots to disk',
    'save-artifacts': 'Save all gathered artifacts to disk',
    'audit-whitelist': 'Comma separated list of audits to run',
    'list-all-audits': 'Prints a list of all available audits and exits',
    'list-trace-categories': 'Prints a list of all required trace categories and exits',
    'config-path': 'The absolute path to the config JSON.'
  })

  .group([
    'output',
    'output-path'
  ], 'Output:')
  .describe({
    'output': 'Reporter for the results',
    'output-path': `The file path to output the results
Example: --output-path=./lighthouse-results.html`
  })

  // boolean values
  .boolean([
    'save-assets',
    'save-artifacts',
    'list-all-audits',
    'list-trace-categories',
    'verbose',
    'quiet',
    'help',
    'version'
  ])

  .choices('output', Object.values(Printer.OUTPUT_MODE))

  // default values
  .default('mobile', true)
  .default('load-page', true)
  .default('audit-whitelist', 'all')
  .default('output', Printer.OUTPUT_MODE.pretty)
  .default('output-path', 'stdout')
  .check(argv => {
    // Make sure lighthouse has been passed a url, or at least one of --list-all-audits
    // or --list-trace-categories. If not, stop the program and ask for a url
    if (!argv.listAllAudits && !argv.listTraceCategories && argv._.length === 0) {
      throw new Error('Please provide a url');
    }

    return true;
  })
  .argv;

if (cli.listAllAudits) {
  const audits = lighthouse
      .getAuditList()
      .map(i => {
        return i.replace(/\.js$/, '');
      });

  process.stdout.write(JSON.stringify({audits}));
  process.exit(0);
}

if (cli.listTraceCategories) {
  const traceCategories = lighthouse.traceCategories;

  process.stdout.write(JSON.stringify({traceCategories}));
  process.exit(0);
}

const url = cli._[0];
const outputMode = cli.output;
const outputPath = cli.outputPath;
const flags = cli;
const config = (cli.configPath && require(cli.configPath)) || null;

// set logging preferences
flags.logLevel = 'info';
if (cli.verbose) {
  flags.logLevel = 'verbose';
} else if (cli.quiet) {
  flags.logLevel = 'error';
}

// Normalize audit whitelist.
if (!flags.auditWhitelist || flags.auditWhitelist === 'all') {
  flags.auditWhitelist = null;
} else {
  flags.auditWhitelist = new Set(flags.auditWhitelist.split(',').map(a => a.toLowerCase()));
}

// kick off a lighthouse run
lighthouse(url, flags, config)
  .then(results => Printer.write(results, outputMode, outputPath))
  .then(results => {
    if (outputMode !== 'html') {
      Printer.write(results, 'html', './last-run-results.html');
    }
    return;
  })
  .catch(err => {
    if (err.code === 'ECONNREFUSED') {
      console.error('Unable to connect to Chrome. Did you run ./scripts/launch-chrome.sh ?');
    } else {
      console.error('Runtime error encountered:', err);
      console.error(err.stack);
    }
    process.exit(1);
  });
<commit_msg>CLI shouldn't necc exit on semver check<commit_after>#!/usr/bin/env node
/**
 * @license
 * Copyright 2016 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const yargs = require('yargs');
const semver = require('semver');
const Printer = require('./printer');
const lighthouse = require('../lighthouse-core');

// node 5.x required due to use of ES2015 features, like spread operator
if (semver.lt(process.version, '5.0.0')) {
  console.warn('Compatibility error', 'Lighthouse requires node 5+ or 4 with --harmony');
}

const cli = yargs
  .help('help')
  .version()
  .showHelpOnFail(false, 'Specify --help for available options')

  .usage('$0 url')

  // List of options
  .group([
    'verbose',
    'quiet'
  ], 'Logging:')
  .describe({
    verbose: 'Displays verbose logging',
    quiet: 'Displays no progress or debug logs'
  })

  .group([
    'mobile',
    'load-page',
    'save-assets',
    'save-artifacts',
    'audit-whitelist',
    'list-all-audits',
    'list-trace-categories',
    'config-path'
  ], 'Configuration:')
  .describe({
    'mobile': 'Emulates a Nexus 5X',
    'load-page': 'Loads the page',
    'save-assets': 'Save the trace contents & screenshots to disk',
    'save-artifacts': 'Save all gathered artifacts to disk',
    'audit-whitelist': 'Comma separated list of audits to run',
    'list-all-audits': 'Prints a list of all available audits and exits',
    'list-trace-categories': 'Prints a list of all required trace categories and exits',
    'config-path': 'The absolute path to the config JSON.'
  })

  .group([
    'output',
    'output-path'
  ], 'Output:')
  .describe({
    'output': 'Reporter for the results',
    'output-path': `The file path to output the results
Example: --output-path=./lighthouse-results.html`
  })

  // boolean values
  .boolean([
    'save-assets',
    'save-artifacts',
    'list-all-audits',
    'list-trace-categories',
    'verbose',
    'quiet',
    'help',
    'version'
  ])

  .choices('output', Object.values(Printer.OUTPUT_MODE))

  // default values
  .default('mobile', true)
  .default('load-page', true)
  .default('audit-whitelist', 'all')
  .default('output', Printer.OUTPUT_MODE.pretty)
  .default('output-path', 'stdout')
  .check(argv => {
    // Make sure lighthouse has been passed a url, or at least one of --list-all-audits
    // or --list-trace-categories. If not, stop the program and ask for a url
    if (!argv.listAllAudits && !argv.listTraceCategories && argv._.length === 0) {
      throw new Error('Please provide a url');
    }

    return true;
  })
  .argv;

if (cli.listAllAudits) {
  const audits = lighthouse
      .getAuditList()
      .map(i => {
        return i.replace(/\.js$/, '');
      });

  process.stdout.write(JSON.stringify({audits}));
  process.exit(0);
}

if (cli.listTraceCategories) {
  const traceCategories = lighthouse.traceCategories;

  process.stdout.write(JSON.stringify({traceCategories}));
  process.exit(0);
}

const url = cli._[0];
const outputMode = cli.output;
const outputPath = cli.outputPath;
const flags = cli;
const config = (cli.configPath && require(cli.configPath)) || null;

// set logging preferences
flags.logLevel = 'info';
if (cli.verbose) {
  flags.logLevel = 'verbose';
} else if (cli.quiet) {
  flags.logLevel = 'error';
}

// Normalize audit whitelist.
if (!flags.auditWhitelist || flags.auditWhitelist === 'all') {
  flags.auditWhitelist = null;
} else {
  flags.auditWhitelist = new Set(flags.auditWhitelist.split(',').map(a => a.toLowerCase()));
}

// kick off a lighthouse run
lighthouse(url, flags, config)
  .then(results => Printer.write(results, outputMode, outputPath))
  .then(results => {
    if (outputMode !== 'html') {
      Printer.write(results, 'html', './last-run-results.html');
    }
    return;
  })
  .catch(err => {
    if (err.code === 'ECONNREFUSED') {
      console.error('Unable to connect to Chrome. Did you run ./scripts/launch-chrome.sh ?');
    } else {
      console.error('Runtime error encountered:', err);
      console.error(err.stack);
    }
    process.exit(1);
  });
<|endoftext|>


<commit_before>(function(){
    if(typeof EthereumProvider === "undefined"){
    var callbackId = 0;
    var callbacks = {};

    var bridgeSend = function (data) {
        ReactNativeWebView.postMessage(JSON.stringify(data));
    }

    var history = window.history;
    var pushState = history.pushState;
    history.pushState = function(state) {
        setTimeout(function () {
            bridgeSend({
               type: 'history-state-changed',
               navState: { url: location.href, title: document.title }
            });
        }, 100);
        return pushState.apply(history, arguments);
    };

    function sendAPIrequest(permission, params) {
        var messageId = callbackId++;
        var params = params || {};

        bridgeSend({
            type: 'api-request',
            permission: permission,
            messageId: messageId,
            params: params
        });

        return new Promise(function (resolve, reject) {
            params['resolve'] = resolve;
            params['reject'] = reject;
            callbacks[messageId] = params;
        });
    }

    function qrCodeResponse(data, callback){
        var result = data.data;
        var regex = new RegExp(callback.regex);
        if (!result) {
            if (callback.reject) {
                callback.reject(new Error("Cancelled"));
            }
        }
        else if (regex.test(result)) {
            if (callback.resolve) {
                callback.resolve(result);
            }
        } else {
            if (callback.reject) {
                callback.reject(new Error("Doesn't match"));
            }
        }
    }

    function Unauthorized() {
      this.name = "Unauthorized";
      this.id = 4100;
      this.code = 4100;
      this.message = "The requested method and/or account has not been authorized by the user.";
    }
    Unauthorized.prototype = Object.create(Error.prototype);

    function UserRejectedRequest() {
      this.name = "UserRejectedRequest";
      this.id = 4001;
      this.code = 4001;
      this.message = "The user rejected the request.";
    }
    UserRejectedRequest.prototype = Object.create(Error.prototype);
    ReactNativeWebView.onMessage = function (message)
    {
        data = JSON.parse(message);
        var id = data.messageId;
        var callback = callbacks[id];

        if (callback) {
            if (data.type === "api-response") {
                if (data.permission == 'qr-code'){
                    qrCodeResponse(data, callback);
                } else if (data.isAllowed) {
                    if (data.permission == 'web3') {
                        var selectedAddress = data.data[0]
                        window.statusAppcurrentAccountAddress = selectedAddress;
                        // Set deprecated metamask fields
                        window.ethereum.selectedAddress = selectedAddress;
                        window.ethereum.emit("accountsChanged", data.data);
                    }
                    callback.resolve(data.data);
                } else {
                    callback.reject(new UserRejectedRequest());
                }
            }
            else if (data.type === "web3-send-async-callback")
            {
                if (callback.beta)
                {
                    if (data.error)
                    {
                        if (data.error.code == 4100)
                            callback.reject(new Unauthorized());
                        else
                            callback.reject(data.error);
                    }
                    else
                    {
                        callback.resolve(data.result.result);
                    }
                }
                else if (callback.results)
                {
                    callback.results.push(data.error || data.result);
                    if (callback.results.length == callback.num)
                        callback.callback(undefined, callback.results);
                }
                else
                {
                    callback.callback(data.error, data.result);
                }
            }
        }
    };

    function web3Response (payload, result){
        return {id: payload.id,
                jsonrpc: "2.0",
                result: result};
    }

    function getSyncResponse (payload) {
        if (payload.method == "eth_accounts" && (typeof window.statusAppcurrentAccountAddress !== "undefined")) {
            return web3Response(payload, [window.statusAppcurrentAccountAddress])
        } else if (payload.method == "eth_coinbase" && (typeof window.statusAppcurrentAccountAddress !== "undefined")) {
            return web3Response(payload, window.statusAppcurrentAccountAddress)
        } else if (payload.method == "net_version"){
            return web3Response(payload, window.statusAppNetworkId)
        } else if (payload.method == "eth_chainId"){
            return web3Response(payload, "0x" + window.statusAppNetworkId.toString(16))
        } else if (payload.method == "eth_uninstallFilter"){
            return web3Response(payload, true);
        } else {
            return null;
        }
    }

    var StatusAPI = function () {};

    StatusAPI.prototype.getContactCode = function () {
        return sendAPIrequest('contact-code');
    };

    var EthereumProvider = function () {};

    EthereumProvider.prototype.isStatus = true;
    EthereumProvider.prototype.status = new StatusAPI();
    EthereumProvider.prototype.isConnected = function () { return true; };
    // Set legacy metamask fields https://docs.metamask.io/guide/ethereum-provider.html#legacy-api
    EthereumProvider.prototype.networkVersion = window.statusAppNetworkId;
    EthereumProvider.prototype.chainId = "0x" + window.statusAppNetworkId.toString(16);

    EthereumProvider.prototype._events = {};

    EthereumProvider.prototype.on = function(name, listener) {
        if (!this._events[name]) {
          this._events[name] = [];
        }
        this._events[name].push(listener);
    }

    EthereumProvider.prototype.removeListener = function (name, listenerToRemove) {
        if (!this._events[name]) {
          return
        }

        const filterListeners = (listener) => listener !== listenerToRemove;
        this._events[name] = this._events[name].filter(filterListeners);
    }

    EthereumProvider.prototype.removeAllListeners = function () {
        this._events = {};
    }

    EthereumProvider.prototype.emit = function (name, data) {
        if (!this._events[name]) {
          return
        }
        this._events[name].forEach(cb => cb(data));
    }
    EthereumProvider.prototype.enable = function () {
        if (window.statusAppDebug) { console.log("enable"); }
        return sendAPIrequest('web3');
    };

    EthereumProvider.prototype.scanQRCode = function (regex) {
        return sendAPIrequest('qr-code', {regex: regex});
    };

    EthereumProvider.prototype.request = function (requestArguments)
    {
         if (window.statusAppDebug) { console.log("request: " + JSON.stringify(requestArguments)); }
         if (!requestArguments) {
           return new Error('Request is not valid.');
         }
         var method = requestArguments.method;

         if (!method) {
           return new Error('Request is not valid.');
         }

         //Support for legacy send method
         if (typeof method !== 'string') {
           return this.sendSync(method);
         }

         if (method == 'eth_requestAccounts'){
             return sendAPIrequest('web3');
         }

         var syncResponse = getSyncResponse({method: method});
         if (syncResponse){
             return new Promise(function (resolve, reject) {
                                        resolve(syncResponse.result);
                                    });
         }

         var messageId = callbackId++;
         var payload = {id:      messageId,
                        jsonrpc: "2.0",
                        method:  method,
                        params:  requestArguments.params};

         bridgeSend({type:      'web3-send-async-read-only',
                     messageId: messageId,
                     payload:   payload});

         return new Promise(function (resolve, reject) {
                                callbacks[messageId] = {beta:    true,
                                                        resolve: resolve,
                                                        reject:  reject};
                            });
    };

    // (DEPRECATED) Support for legacy send method
    EthereumProvider.prototype.send = function (method, params = [])
    {
        if (window.statusAppDebug) { console.log("send (legacy): " + method);}
        return this.request({method: method, params: params});
    }

    // (DEPRECATED) Support for legacy sendSync method
    EthereumProvider.prototype.sendSync = function (payload)
    {
        if (window.statusAppDebug) { console.log("sendSync (legacy)" + JSON.stringify(payload));}
        if (payload.method == "eth_uninstallFilter"){
            this.sendAsync(payload, function (res, err) {})
        }
        var syncResponse = getSyncResponse(payload);
        if (syncResponse){
            return syncResponse;
        } else {
            return web3Response(payload, null);
        }
    };

    // (DEPRECATED) Support for legacy sendAsync method
    EthereumProvider.prototype.sendAsync = function (payload, callback)
    {
      if (window.statusAppDebug) { console.log("sendAsync (legacy)" + JSON.stringify(payload));}
      if (!payload) {
          return new Error('Request is not valid.');
      }
      if (payload.method == 'eth_requestAccounts'){
          return sendAPIrequest('web3');
      }
      var syncResponse = getSyncResponse(payload);
      if (syncResponse && callback) {
          callback(null, syncResponse);
      }
      else
      {
          var messageId = callbackId++;

          if (Array.isArray(payload))
          {
              callbacks[messageId] = {num:      payload.length,
                                      results:  [],
                                      callback: callback};
              for (var i in payload) {
                  bridgeSend({type:      'web3-send-async-read-only',
                              messageId: messageId,
                              payload:   payload[i]});
              }
          }
          else
          {
              callbacks[messageId] = {callback: callback};
              bridgeSend({type:      'web3-send-async-read-only',
                          messageId: messageId,
                          payload:   payload});
          }
      }
    };
    }

    window.ethereum = new EthereumProvider();
})();
<commit_msg>fix eth_chainId<commit_after>(function(){
    if(typeof EthereumProvider === "undefined"){
    var callbackId = 0;
    var callbacks = {};

    var bridgeSend = function (data) {
        ReactNativeWebView.postMessage(JSON.stringify(data));
    }

    var history = window.history;
    var pushState = history.pushState;
    history.pushState = function(state) {
        setTimeout(function () {
            bridgeSend({
               type: 'history-state-changed',
               navState: { url: location.href, title: document.title }
            });
        }, 100);
        return pushState.apply(history, arguments);
    };

    function sendAPIrequest(permission, params) {
        var messageId = callbackId++;
        var params = params || {};

        bridgeSend({
            type: 'api-request',
            permission: permission,
            messageId: messageId,
            params: params
        });

        return new Promise(function (resolve, reject) {
            params['resolve'] = resolve;
            params['reject'] = reject;
            callbacks[messageId] = params;
        });
    }

    function qrCodeResponse(data, callback){
        var result = data.data;
        var regex = new RegExp(callback.regex);
        if (!result) {
            if (callback.reject) {
                callback.reject(new Error("Cancelled"));
            }
        }
        else if (regex.test(result)) {
            if (callback.resolve) {
                callback.resolve(result);
            }
        } else {
            if (callback.reject) {
                callback.reject(new Error("Doesn't match"));
            }
        }
    }

    function Unauthorized() {
      this.name = "Unauthorized";
      this.id = 4100;
      this.code = 4100;
      this.message = "The requested method and/or account has not been authorized by the user.";
    }
    Unauthorized.prototype = Object.create(Error.prototype);

    function UserRejectedRequest() {
      this.name = "UserRejectedRequest";
      this.id = 4001;
      this.code = 4001;
      this.message = "The user rejected the request.";
    }
    UserRejectedRequest.prototype = Object.create(Error.prototype);
    ReactNativeWebView.onMessage = function (message)
    {
        data = JSON.parse(message);
        var id = data.messageId;
        var callback = callbacks[id];

        if (callback) {
            if (data.type === "api-response") {
                if (data.permission == 'qr-code'){
                    qrCodeResponse(data, callback);
                } else if (data.isAllowed) {
                    if (data.permission == 'web3') {
                        var selectedAddress = data.data[0]
                        window.statusAppcurrentAccountAddress = selectedAddress;
                        // Set deprecated metamask fields
                        window.ethereum.selectedAddress = selectedAddress;
                        window.ethereum.emit("accountsChanged", data.data);
                    }
                    callback.resolve(data.data);
                } else {
                    callback.reject(new UserRejectedRequest());
                }
            }
            else if (data.type === "web3-send-async-callback")
            {
                if (callback.beta)
                {
                    if (data.error)
                    {
                        if (data.error.code == 4100)
                            callback.reject(new Unauthorized());
                        else
                            callback.reject(data.error);
                    }
                    else
                    {
                        callback.resolve(data.result.result);
                    }
                }
                else if (callback.results)
                {
                    callback.results.push(data.error || data.result);
                    if (callback.results.length == callback.num)
                        callback.callback(undefined, callback.results);
                }
                else
                {
                    callback.callback(data.error, data.result);
                }
            }
        }
    };

    function web3Response (payload, result){
        return {id: payload.id,
                jsonrpc: "2.0",
                result: result};
    }

    function getSyncResponse (payload) {
        if (payload.method == "eth_accounts" && (typeof window.statusAppcurrentAccountAddress !== "undefined")) {
            return web3Response(payload, [window.statusAppcurrentAccountAddress])
        } else if (payload.method == "eth_coinbase" && (typeof window.statusAppcurrentAccountAddress !== "undefined")) {
            return web3Response(payload, window.statusAppcurrentAccountAddress)
        } else if (payload.method == "net_version"){
            return web3Response(payload, window.statusAppNetworkId)
        } else if (payload.method == "eth_chainId"){
            return web3Response(payload, "0x" + Number(window.statusAppNetworkId).toString(16))
        } else if (payload.method == "eth_uninstallFilter"){
            return web3Response(payload, true);
        } else {
            return null;
        }
    }

    var StatusAPI = function () {};

    StatusAPI.prototype.getContactCode = function () {
        return sendAPIrequest('contact-code');
    };

    var EthereumProvider = function () {};

    EthereumProvider.prototype.isStatus = true;
    EthereumProvider.prototype.status = new StatusAPI();
    EthereumProvider.prototype.isConnected = function () { return true; };
    // Set legacy metamask fields https://docs.metamask.io/guide/ethereum-provider.html#legacy-api
    EthereumProvider.prototype.networkVersion = window.statusAppNetworkId;
    EthereumProvider.prototype.chainId = "0x" + Number(window.statusAppNetworkId).toString(16);

    EthereumProvider.prototype._events = {};

    EthereumProvider.prototype.on = function(name, listener) {
        if (!this._events[name]) {
          this._events[name] = [];
        }
        this._events[name].push(listener);
    }

    EthereumProvider.prototype.removeListener = function (name, listenerToRemove) {
        if (!this._events[name]) {
          return
        }

        const filterListeners = (listener) => listener !== listenerToRemove;
        this._events[name] = this._events[name].filter(filterListeners);
    }

    EthereumProvider.prototype.removeAllListeners = function () {
        this._events = {};
    }

    EthereumProvider.prototype.emit = function (name, data) {
        if (!this._events[name]) {
          return
        }
        this._events[name].forEach(cb => cb(data));
    }
    EthereumProvider.prototype.enable = function () {
        if (window.statusAppDebug) { console.log("enable"); }
        return sendAPIrequest('web3');
    };

    EthereumProvider.prototype.scanQRCode = function (regex) {
        return sendAPIrequest('qr-code', {regex: regex});
    };

    EthereumProvider.prototype.request = function (requestArguments)
    {
         if (window.statusAppDebug) { console.log("request: " + JSON.stringify(requestArguments)); }
         if (!requestArguments) {
           return new Error('Request is not valid.');
         }
         var method = requestArguments.method;

         if (!method) {
           return new Error('Request is not valid.');
         }

         //Support for legacy send method
         if (typeof method !== 'string') {
           return this.sendSync(method);
         }

         if (method == 'eth_requestAccounts'){
             return sendAPIrequest('web3');
         }

         var syncResponse = getSyncResponse({method: method});
         if (syncResponse){
             return new Promise(function (resolve, reject) {
                                        if (window.statusAppDebug) { console.log("resolve sync: " + resolve + " " + JSON.stringify(syncResponse.result)); }
                                        resolve(syncResponse.result);
                                    });
         }

         var messageId = callbackId++;
         var payload = {id:      messageId,
                        jsonrpc: "2.0",
                        method:  method,
                        params:  requestArguments.params};

         bridgeSend({type:      'web3-send-async-read-only',
                     messageId: messageId,
                     payload:   payload});

         return new Promise(function (resolve, reject) {
                                callbacks[messageId] = {beta:    true,
                                                        resolve: resolve,
                                                        reject:  reject};
                            });
    };

    // (DEPRECATED) Support for legacy send method
    EthereumProvider.prototype.send = function (method, params = [])
    {
        if (window.statusAppDebug) { console.log("send (legacy): " + method);}
        return this.request({method: method, params: params});
    }

    // (DEPRECATED) Support for legacy sendSync method
    EthereumProvider.prototype.sendSync = function (payload)
    {
        if (window.statusAppDebug) { console.log("sendSync (legacy)" + JSON.stringify(payload));}
        if (payload.method == "eth_uninstallFilter"){
            this.sendAsync(payload, function (res, err) {})
        }
        var syncResponse = getSyncResponse(payload);
        if (syncResponse){
            return syncResponse;
        } else {
            return web3Response(payload, null);
        }
    };

    // (DEPRECATED) Support for legacy sendAsync method
    EthereumProvider.prototype.sendAsync = function (payload, callback)
    {
      if (window.statusAppDebug) { console.log("sendAsync (legacy)" + JSON.stringify(payload));}
      if (!payload) {
          return new Error('Request is not valid.');
      }
      if (payload.method == 'eth_requestAccounts'){
          return sendAPIrequest('web3');
      }
      var syncResponse = getSyncResponse(payload);
      if (syncResponse && callback) {
          callback(null, syncResponse);
      }
      else
      {
          var messageId = callbackId++;

          if (Array.isArray(payload))
          {
              callbacks[messageId] = {num:      payload.length,
                                      results:  [],
                                      callback: callback};
              for (var i in payload) {
                  bridgeSend({type:      'web3-send-async-read-only',
                              messageId: messageId,
                              payload:   payload[i]});
              }
          }
          else
          {
              callbacks[messageId] = {callback: callback};
              bridgeSend({type:      'web3-send-async-read-only',
                          messageId: messageId,
                          payload:   payload});
          }
      }
    };
    }

    window.ethereum = new EthereumProvider();
})();
<|endoftext|>


<commit_before>goog.module('google3.javascript.ads.interactivemedia.sdk.dai.sample.google_cast.player');

const NAMESPACE = 'urn:x-cast:com.google.ads.ima.cast';

class Player {
  /**
   * Represents the receiver
   * @param {!Object} mediaElement - the cast media player element
   */
  constructor(mediaElement) {
    /**
     * the fallback stream to play if loading fails
     * @type {string}
     * @private
     * @const
     */
    this.backupStream_ = 'http://storage.googleapis.com/testtopbox-public/' +
        'video_content/bbb/master.m3u8';

    /**
     * the cast context object provided by the CAF framework.
     * @type {!Object}
     * @private
     * @const
     */
    this.castContext_ = cast.framework.CastReceiverContext.getInstance();

    /**
     * the player manager object, provided by the CAF framework.
     * @type {!Object}
     * @private
     * @const
     */
    this.playerManager_ = this.castContext_.getPlayerManager();

    /**
     * the video player contained within the cast media player element.
     * @type {!HTMLMediaElement}
     * @private
     * @const
     */
    this.mediaElement_ = mediaElement.getMediaElement();

    /**
     * This is the stream manager object for IMA SDK.
     * @type {?Object}
     * @private
     */
    this.streamManager_ = null;

    /**
     * Stores the timestamp where playback will start, in seconds, for
     * bookmarking.
     * @type {number}
     * @private
     */
    this.startTime_ = 0;

    /**
     * Stores a flag to identify whether an ad is currently playing.
     * @type {boolean}
     * @private
     */
    this.adIsPlaying_ = false;

    /**
     * Stores the timestamp to seek to when ad completes, for snapback.
     * -1 indicates that snapback has not been requested.
     * @type {number}
     * @private
     */
    this.seekToTimeAfterAdBreak_ = -1;
  }

  /** Initializes CAF and IMA SDK */
  initialize() {
    // Map of namespace names to their types.
    const options = new cast.framework.CastReceiverOptions();
    options.customNamespaces = {};
    options.customNamespaces[NAMESPACE] =
        cast.framework.system.MessageType.STRING;
    this.castContext_.start(options);
    this.streamManager_ =
        new google.ima.dai.api.StreamManager(this.mediaElement_);
  }

  /** Attaches event listeners and other callbacks. */
  setupCallbacks() {
    // Receives messages from sender app.
    this.castContext_.addCustomMessageListener(NAMESPACE, (event) => {
      this.processSenderMessage_(event.data);
    });

    this.attachPlayerManagerCallbacks_();
    this.attachStreamManagerListeners_();
  }

  /**
   * Parses messages from sender apps. The message is a comma separated
   * string consisting of a function name followed by a set of parameters.
   * @param {string} message - The raw message from the sender app.
   * @private
   */
  processSenderMessage_(message) {
    console.log('Received message from sender: ' + message);
    const messageArray = message.split(',');
    const method = messageArray[0];
    switch (method) {
      case 'bookmark':
        const time = parseFloat(messageArray[1]);
        const bookmarkTime = this.streamManager_.contentTimeForStreamTime(time);
        this.broadcast('bookmark,' + bookmarkTime);
        this.bookmark(time);
        break;
      case 'getContentTime':
        const contentTime = this.getContentTime();
        this.broadcast('contentTime,' + contentTime);
        break;
      default:
        this.broadcast('Message not recognized');
        break;
    }
  }

  /**
   * Attaches message interceptors and event listeners to connet IMA to CAF.
   * @private
   */
  attachPlayerManagerCallbacks_() {
    // This intercepts the CAF load process, to load the IMA stream manager and
    // make a DAI stream request. It then injests the stream URL into the
    // original LOAD message, before passing it to CAF
    this.playerManager_.setMessageInterceptor(
        cast.framework.messages.MessageType.LOAD, (request) => {
          return this.initializeStreamManager_(request);
        });

    // This intercepts CAF seek requests to cancel them in the case that an ad
    // is playing, and to modify them to enable snapback
    this.playerManager_.setMessageInterceptor(
        cast.framework.messages.MessageType.SEEK, (seekRequest) => {
          return this.processSeekRequest_(seekRequest);
        });

    // This passes ID3 events from the stream to the IMA to allow for updating
    // stream events on the fly in live streams
    this.playerManager_.addEventListener(
        cast.framework.events.EventType.ID3, (event) => {
          // pass ID3 events from the stream to IMA to update live stream
          // cuepoints
          this.streamManager_.processMetadata(
              'ID3', event.segmentData, event.timestamp);
        });

    this.playerManager_.addEventListener(
        [
          cast.framework.events.EventType.TIMED_METADATA_ENTER,
          cast.framework.events.EventType.TIMED_METADATA_CHANGED,
          cast.framework.events.EventType.TIMED_METADATA_EXIT,
        ],
        (event) => this.handleTimedMetadataEvent_(event));
  }

  /**
   * Handles timedmetadata updates from the player manager.
   * @param {!cast.framework.events.TimedMetadataEvent} event
   * @private
   */
  handleTimedMetadataEvent_(event) {
    if (!event.timedMetadataInfo) {
      return;
    }
    if (event.timedMetadataInfo.dashTimedMetadata &&
        event.timedMetadataInfo.dashTimedMetadata.eventElement) {
      this.streamManager_.processMetadata(
          event.timedMetadataInfo.dashTimedMetadata.schemeIdUri,
          event.timedMetadataInfo.dashTimedMetadata.eventElement.getAttribute(
              'messageData'),
          event.timedMetadataInfo.startTime);
    }
  }

  /**
   * Attaches IMA event managers
   * @private
   */
  attachStreamManagerListeners_() {
    // This fires at the beginning of each ad break
    this.streamManager_.addEventListener(
        google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED, (event) => {
          this.startAdBreak_();
        });
    // This fires at the end of each ad break
    this.streamManager_.addEventListener(
        google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED, (event) => {
          this.endAdBreak_();
        });
    // This fires periodically while ads are playing
    this.streamManager_.addEventListener(
        google.ima.dai.api.StreamEvent.Type.AD_PROGRESS, (event) => {
          this.updateAdProgress_(event);
        });

    // Log the quartile events to the console for debugging
    const quartileEvents = [
      google.ima.dai.api.StreamEvent.Type.STARTED,
      google.ima.dai.api.StreamEvent.Type.FIRST_QUARTILE,
      google.ima.dai.api.StreamEvent.Type.MIDPOINT,
      google.ima.dai.api.StreamEvent.Type.THIRD_QUARTILE,
      google.ima.dai.api.StreamEvent.Type.COMPLETE
    ];
    this.streamManager_.addEventListener(quartileEvents, (event) => {
      console.log(`IMA SDK Event: ${event.type}`);
    }, false);
  }

  /**
   * initializes the IMA StreamManager and issues a stream request.
   * @param {!Object} request - The request data object from the CAF sender
   * @return {!Promise<!Object>} - The request object with added stream
   *     information
   * @private
   */
  initializeStreamManager_(request) {
    return new Promise((resolve, reject) => {
      // Set media info and resolve promise on successful stream request
      this.streamManager_.addEventListener(
          google.ima.dai.api.StreamEvent.Type.LOADED, (event) => {
            this.broadcast('Stream request successful. Loading stream...');
            request.media.contentUrl = event.getStreamData().url;
            request.media.subtitles = event.getStreamData().subtitles;
            if (event.getStreamData().manifestFormat.toLowerCase() == 'dash') {
              request.media.contentType = 'application/dash+xml';
            }
            resolve(request);
          }, false);

      // Prepare backup stream and resolve promise on stream request error
      this.streamManager_.addEventListener(
          google.ima.dai.api.StreamEvent.Type.ERROR, (event) => {
            this.broadcast('Stream request failed. Loading backup stream...');
            request.media.contentUrl = this.backupStream_;
            resolve(request);
          }, false);

      // Request Stream
      const imaRequestData = request.media.customData;
      this.startTime_ = imaRequestData.startTime;
      const streamRequest = (imaRequestData.assetKey) ?
          new google.ima.dai.api.LiveStreamRequest(imaRequestData) :
          new google.ima.dai.api.VODStreamRequest(imaRequestData);
      this.streamManager_.requestStream(streamRequest);
      document.getElementById('splash').style.display = 'none';

      // For VOD Streams, update start time on media element
      if (this.startTime_ &&
          request.media.streamType ===
              cast.framework.messages.StreamType.BUFFERED) {
        this.mediaElement_.currentTime =
            this.streamManager_.streamTimeForContentTime(this.startTime_);
      }
    });
  }

  /**
   * Intercepts requests to seek and injects necessary information for snapback.
   * Also prevents seeking while ads are playing.
   * @param {!Object} seekRequest - A CAF seek request
   * @return {!Object} - A potentially modified CAF seek request
   * @private
   */
  processSeekRequest_(seekRequest) {
    const seekTo = seekRequest.currentTime;
    const previousCuepoint =
        this.streamManager_.previousCuePointForStreamTime(seekTo);
    if (this.adIsPlaying_) {
      // effectively cancels seek request
      seekRequest.currentTime = this.mediaElement_.currentTime;
    } else if (!previousCuepoint.played) {
      // Adding 0.1 to cuepoint start time because of bug where stream
      // freezes when seeking to certain times in VOD streams.
      seekRequest.currentTime = previousCuepoint.start + 0.1;
      this.seekToTimeAfterAdBreak_ = seekTo;
    }
    return seekRequest;
  }

  /**
   * Sets flags and UI at the start of an ad break.
   * @private
   */
  startAdBreak_() {
    this.adIsPlaying_ = true;
    document.getElementById('ad-ui').style.display = 'block';
    this.broadcast('adBreakStarted');
  }

  /**
   * Sets flags and UI and triggers snapback at the end of an ad break.
   * @private
   */
  endAdBreak_() {
    this.adIsPlaying_ = false;
    document.getElementById('ad-ui').style.display = 'none';
    this.broadcast('adBreakEnded');
    // process any pending snapback request
    if (this.seekToTimeAfterAdBreak_ != -1) {
      this.seek(this.seekToTimeAfterAdBreak_);
      this.seekToTimeAfterAdBreak_ = -1;
    }
  }

  /**
   * Updates ad UI to display progress in ad break.
   * @param {!Object} event - The ad progress event from IMA
   * @private
   */
  updateAdProgress_(event) {
    const adData = event.getStreamData().adProgressData;
    document.getElementById('ad-position').textContext =
        parseInt(adData.adPosition, 10);
    document.getElementById('total-ads').textContext =
        parseInt(adData.totalAds, 10);
    document.getElementById('time-value').textContext =
        Math.ceil(parseFloat(adData.duration) - parseFloat(adData.currentTime));
    document.getElementById('ad-ui').style.display = 'block';
  }

  /**
   * Seeks video playback to specified time if not playing an ad.
   * @param {number} time - The target stream time in seconds, including ads.
   */
  seek(time) {
    if (time > 0 && !this.adIsPlaying_) {
      this.mediaElement_.currentTime = time;
      this.broadcast('Seeking to: ' + time);
    }
  }

  /**
   * Sets a bookmark to a specific time on future playback.
   * @param {number} time - The target stream time in seconds, including ads.
   */
  bookmark(time) {
    this.startTime_ = time;
  }

  /**
   * Gets the current timestamp in the stream, not including ads.
   * @return {number} - The stream time in seconds, without ads.
   */
  getContentTime() {
    const currentTime = this.mediaElement_.currentTime;
    return this.streamManager_.contentTimeForStreamTime(currentTime);
  }

  /**
   * Broadcasts a message to all attached CAF senders
   * @param {string} message - The message to be sent to attached senders
   */
  broadcast(message) {
    console.log(message);
    this.castContext_.sendCustomMessage(NAMESPACE, undefined, message);
  }
}
<commit_msg>Internal change<commit_after>
const NAMESPACE = 'urn:x-cast:com.google.ads.ima.cast';

class Player {
  /**
   * Represents the receiver
   * @param {!Object} mediaElement - the cast media player element
   */
  constructor(mediaElement) {
    /**
     * the fallback stream to play if loading fails
     * @type {string}
     * @private
     * @const
     */
    this.backupStream_ = 'http://storage.googleapis.com/testtopbox-public/' +
        'video_content/bbb/master.m3u8';

    /**
     * the cast context object provided by the CAF framework.
     * @type {!Object}
     * @private
     * @const
     */
    this.castContext_ = cast.framework.CastReceiverContext.getInstance();

    /**
     * the player manager object, provided by the CAF framework.
     * @type {!Object}
     * @private
     * @const
     */
    this.playerManager_ = this.castContext_.getPlayerManager();

    /**
     * the video player contained within the cast media player element.
     * @type {!HTMLMediaElement}
     * @private
     * @const
     */
    this.mediaElement_ = mediaElement.getMediaElement();

    /**
     * This is the stream manager object for IMA SDK.
     * @type {?Object}
     * @private
     */
    this.streamManager_ = null;

    /**
     * Stores the timestamp where playback will start, in seconds, for
     * bookmarking.
     * @type {number}
     * @private
     */
    this.startTime_ = 0;

    /**
     * Stores a flag to identify whether an ad is currently playing.
     * @type {boolean}
     * @private
     */
    this.adIsPlaying_ = false;

    /**
     * Stores the timestamp to seek to when ad completes, for snapback.
     * -1 indicates that snapback has not been requested.
     * @type {number}
     * @private
     */
    this.seekToTimeAfterAdBreak_ = -1;
  }

  /** Initializes CAF and IMA SDK */
  initialize() {
    // Map of namespace names to their types.
    const options = new cast.framework.CastReceiverOptions();
    options.customNamespaces = {};
    options.customNamespaces[NAMESPACE] =
        cast.framework.system.MessageType.STRING;
    this.castContext_.start(options);
    this.streamManager_ =
        new google.ima.dai.api.StreamManager(this.mediaElement_);
  }

  /** Attaches event listeners and other callbacks. */
  setupCallbacks() {
    // Receives messages from sender app.
    this.castContext_.addCustomMessageListener(NAMESPACE, (event) => {
      this.processSenderMessage_(event.data);
    });

    this.attachPlayerManagerCallbacks_();
    this.attachStreamManagerListeners_();
  }

  /**
   * Parses messages from sender apps. The message is a comma separated
   * string consisting of a function name followed by a set of parameters.
   * @param {string} message - The raw message from the sender app.
   * @private
   */
  processSenderMessage_(message) {
    console.log('Received message from sender: ' + message);
    const messageArray = message.split(',');
    const method = messageArray[0];
    switch (method) {
      case 'bookmark':
        const time = parseFloat(messageArray[1]);
        const bookmarkTime = this.streamManager_.contentTimeForStreamTime(time);
        this.broadcast('bookmark,' + bookmarkTime);
        this.bookmark(time);
        break;
      case 'getContentTime':
        const contentTime = this.getContentTime();
        this.broadcast('contentTime,' + contentTime);
        break;
      default:
        this.broadcast('Message not recognized');
        break;
    }
  }

  /**
   * Attaches message interceptors and event listeners to connet IMA to CAF.
   * @private
   */
  attachPlayerManagerCallbacks_() {
    // This intercepts the CAF load process, to load the IMA stream manager and
    // make a DAI stream request. It then injests the stream URL into the
    // original LOAD message, before passing it to CAF
    this.playerManager_.setMessageInterceptor(
        cast.framework.messages.MessageType.LOAD, (request) => {
          return this.initializeStreamManager_(request);
        });

    // This intercepts CAF seek requests to cancel them in the case that an ad
    // is playing, and to modify them to enable snapback
    this.playerManager_.setMessageInterceptor(
        cast.framework.messages.MessageType.SEEK, (seekRequest) => {
          return this.processSeekRequest_(seekRequest);
        });

    // This passes ID3 events from the stream to the IMA to allow for updating
    // stream events on the fly in live streams
    this.playerManager_.addEventListener(
        cast.framework.events.EventType.ID3, (event) => {
          // pass ID3 events from the stream to IMA to update live stream
          // cuepoints
          this.streamManager_.processMetadata(
              'ID3', event.segmentData, event.timestamp);
        });

    this.playerManager_.addEventListener(
        [
          cast.framework.events.EventType.TIMED_METADATA_ENTER,
          cast.framework.events.EventType.TIMED_METADATA_CHANGED,
          cast.framework.events.EventType.TIMED_METADATA_EXIT,
        ],
        (event) => this.handleTimedMetadataEvent_(event));
  }

  /**
   * Handles timedmetadata updates from the player manager.
   * @param {!cast.framework.events.TimedMetadataEvent} event
   * @private
   */
  handleTimedMetadataEvent_(event) {
    if (!event.timedMetadataInfo) {
      return;
    }
    if (event.timedMetadataInfo.dashTimedMetadata &&
        event.timedMetadataInfo.dashTimedMetadata.eventElement) {
      this.streamManager_.processMetadata(
          event.timedMetadataInfo.dashTimedMetadata.schemeIdUri,
          event.timedMetadataInfo.dashTimedMetadata.eventElement.getAttribute(
              'messageData'),
          event.timedMetadataInfo.startTime);
    }
  }

  /**
   * Attaches IMA event managers
   * @private
   */
  attachStreamManagerListeners_() {
    // This fires at the beginning of each ad break
    this.streamManager_.addEventListener(
        google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED, (event) => {
          this.startAdBreak_();
        });
    // This fires at the end of each ad break
    this.streamManager_.addEventListener(
        google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED, (event) => {
          this.endAdBreak_();
        });
    // This fires periodically while ads are playing
    this.streamManager_.addEventListener(
        google.ima.dai.api.StreamEvent.Type.AD_PROGRESS, (event) => {
          this.updateAdProgress_(event);
        });

    // Log the quartile events to the console for debugging
    const quartileEvents = [
      google.ima.dai.api.StreamEvent.Type.STARTED,
      google.ima.dai.api.StreamEvent.Type.FIRST_QUARTILE,
      google.ima.dai.api.StreamEvent.Type.MIDPOINT,
      google.ima.dai.api.StreamEvent.Type.THIRD_QUARTILE,
      google.ima.dai.api.StreamEvent.Type.COMPLETE
    ];
    this.streamManager_.addEventListener(quartileEvents, (event) => {
      console.log(`IMA SDK Event: ${event.type}`);
    }, false);
  }

  /**
   * initializes the IMA StreamManager and issues a stream request.
   * @param {!Object} request - The request data object from the CAF sender
   * @return {!Promise<!Object>} - The request object with added stream
   *     information
   * @private
   */
  initializeStreamManager_(request) {
    return new Promise((resolve, reject) => {
      // Set media info and resolve promise on successful stream request
      this.streamManager_.addEventListener(
          google.ima.dai.api.StreamEvent.Type.LOADED, (event) => {
            this.broadcast('Stream request successful. Loading stream...');
            request.media.contentUrl = event.getStreamData().url;
            request.media.subtitles = event.getStreamData().subtitles;
            if (event.getStreamData().manifestFormat.toLowerCase() == 'dash') {
              request.media.contentType = 'application/dash+xml';
            }
            resolve(request);
          }, false);

      // Prepare backup stream and resolve promise on stream request error
      this.streamManager_.addEventListener(
          google.ima.dai.api.StreamEvent.Type.ERROR, (event) => {
            this.broadcast('Stream request failed. Loading backup stream...');
            request.media.contentUrl = this.backupStream_;
            resolve(request);
          }, false);

      // Request Stream
      const imaRequestData = request.media.customData;
      this.startTime_ = imaRequestData.startTime;
      const streamRequest = (imaRequestData.assetKey) ?
          new google.ima.dai.api.LiveStreamRequest(imaRequestData) :
          new google.ima.dai.api.VODStreamRequest(imaRequestData);
      this.streamManager_.requestStream(streamRequest);
      document.getElementById('splash').style.display = 'none';

      // For VOD Streams, update start time on media element
      if (this.startTime_ &&
          request.media.streamType ===
              cast.framework.messages.StreamType.BUFFERED) {
        this.mediaElement_.currentTime =
            this.streamManager_.streamTimeForContentTime(this.startTime_);
      }
    });
  }

  /**
   * Intercepts requests to seek and injects necessary information for snapback.
   * Also prevents seeking while ads are playing.
   * @param {!Object} seekRequest - A CAF seek request
   * @return {!Object} - A potentially modified CAF seek request
   * @private
   */
  processSeekRequest_(seekRequest) {
    const seekTo = seekRequest.currentTime;
    const previousCuepoint =
        this.streamManager_.previousCuePointForStreamTime(seekTo);
    if (this.adIsPlaying_) {
      // effectively cancels seek request
      seekRequest.currentTime = this.mediaElement_.currentTime;
    } else if (!previousCuepoint.played) {
      // Adding 0.1 to cuepoint start time because of bug where stream
      // freezes when seeking to certain times in VOD streams.
      seekRequest.currentTime = previousCuepoint.start + 0.1;
      this.seekToTimeAfterAdBreak_ = seekTo;
    }
    return seekRequest;
  }

  /**
   * Sets flags and UI at the start of an ad break.
   * @private
   */
  startAdBreak_() {
    this.adIsPlaying_ = true;
    document.getElementById('ad-ui').style.display = 'block';
    this.broadcast('adBreakStarted');
  }

  /**
   * Sets flags and UI and triggers snapback at the end of an ad break.
   * @private
   */
  endAdBreak_() {
    this.adIsPlaying_ = false;
    document.getElementById('ad-ui').style.display = 'none';
    this.broadcast('adBreakEnded');
    // process any pending snapback request
    if (this.seekToTimeAfterAdBreak_ != -1) {
      this.seek(this.seekToTimeAfterAdBreak_);
      this.seekToTimeAfterAdBreak_ = -1;
    }
  }

  /**
   * Updates ad UI to display progress in ad break.
   * @param {!Object} event - The ad progress event from IMA
   * @private
   */
  updateAdProgress_(event) {
    const adData = event.getStreamData().adProgressData;
    document.getElementById('ad-position').textContext =
        parseInt(adData.adPosition, 10);
    document.getElementById('total-ads').textContext =
        parseInt(adData.totalAds, 10);
    document.getElementById('time-value').textContext =
        Math.ceil(parseFloat(adData.duration) - parseFloat(adData.currentTime));
    document.getElementById('ad-ui').style.display = 'block';
  }

  /**
   * Seeks video playback to specified time if not playing an ad.
   * @param {number} time - The target stream time in seconds, including ads.
   */
  seek(time) {
    if (time > 0 && !this.adIsPlaying_) {
      this.mediaElement_.currentTime = time;
      this.broadcast('Seeking to: ' + time);
    }
  }

  /**
   * Sets a bookmark to a specific time on future playback.
   * @param {number} time - The target stream time in seconds, including ads.
   */
  bookmark(time) {
    this.startTime_ = time;
  }

  /**
   * Gets the current timestamp in the stream, not including ads.
   * @return {number} - The stream time in seconds, without ads.
   */
  getContentTime() {
    const currentTime = this.mediaElement_.currentTime;
    return this.streamManager_.contentTimeForStreamTime(currentTime);
  }

  /**
   * Broadcasts a message to all attached CAF senders
   * @param {string} message - The message to be sent to attached senders
   */
  broadcast(message) {
    console.log(message);
    this.castContext_.sendCustomMessage(NAMESPACE, undefined, message);
  }
}
<|endoftext|>


<commit_before>module.exports = toLdp
module.exports.traverse = traverse

var jsonpointer = require('jsonpointer')

function isLeaf (resource) {
  return ['string', 'number'].indexOf(typeof resource) > -1
}

function toLdp (json, depth) {
  if (!depth) depth = 1

  var preds = {'contains': []}

  Object.keys(json).sort()
    .forEach(function (resource) {
      // never skip @ properties
      if (resource.substr(0, 1) === '@') {
        preds[resource] = json[resource]
      } else
      // Add leafs
      if (isLeaf(json[resource])) {
        preds[resource] = json[resource]
      }
      // add containment triple
      else {
        preds['contains'].push(resource)
        // if we are allowed to show more, recurse
        if (depth - 1 > 0) {
          preds[resource] = toLdp(json[resource], depth - 1)
        }
        // otherwise, show whether things are containers
        else {
          // TODO maybe everything is a container?
        }
      }
    })

  if (preds['contains'].length === 0) {
    delete preds['contains']
  }
  // TODO: preds['@type'] = 'https://www.w3.org/ns/ldp#Container'
  return preds
}

function traverse (json, path, depth) {
  if (path === '/') path = ''
  return toLdp(jsonpointer.get(json, path), depth)
}
<commit_msg>no json returns null<commit_after>module.exports = toLdp
module.exports.traverse = traverse

var jsonpointer = require('jsonpointer')

function isLeaf (resource) {
  return ['string', 'number'].indexOf(typeof resource) > -1
}

function toLdp (json, depth) {
  if (!json) {
    return null
  }

  if (!depth) depth = 1
  var preds = {'contains': []}

  Object.keys(json)
    .forEach(function (resource) {
      // never skip @ properties
      if (resource.substr(0, 1) === '@') {
        preds[resource] = json[resource]
      } else
      // Add leafs
      if (isLeaf(json[resource])) {
        preds[resource] = json[resource]
      }
      // add containment triple
      else {
        preds['contains'].push(resource)
        // if we are allowed to show more, recurse
        if (depth - 1 > 0) {
          preds[resource] = toLdp(json[resource], depth - 1)
        }
        // otherwise, show whether things are containers
        else {
          // TODO maybe everything is a container?
        }
      }
    })

  if (preds['contains'].length === 0) {
    delete preds['contains']
  }
  // TODO: preds['@type'] = 'https://www.w3.org/ns/ldp#Container'
  return preds
}

function traverse (json, path, depth) {
  if (path === '/') path = ''
  return toLdp(jsonpointer.get(json, path), depth)
}
<|endoftext|>


<commit_before>'use strict';

const getRanking = require('./ranking');

let gameState, myplayer;
module.exports = {
  VERSION: "It's a long way to the top",
  bet_request: function(game_state, bet) {
    new Promise((resolve, reject) => {
        gameState =  game_state;
        myplayer = game_state.players[game_state.in_action];
        console.log(myplayer.hole_cards);
        console.log(game_state);

        //Check for zero phase

        let promise;
        if(gameState.community_cards.length <= 3){
          promise = Promise.resolve(phase_zero());
        } else {
          promise = Promise.resolve(phase_two());
        }
        promise.then(resolve, reject);
    }).then(value => {
        bet(Math.round(value));
    }).catch(err => {
        console.log('ERROR', err);
    });
  },
  showdown: function(game_state) {
  }
};

function phase_zero (){

  const highCards = myplayer.hole_cards.filter(isHighCard);
  if(highCards.length > 0 && isSmallBlind()) {
    console.log('we have a high card and it is still small blind - call!');
    return callMax(gameState.small_blind * 4);
  }
  const haveHighCard = highCards.length > 0;
  if(highCards.length > 1) {
    return minimalRaise();
  } else if(haveHighCard) {
    return callMax(4 * gameState.small_blind);
  }

  const first = myplayer.hole_cards[0];
  const second = myplayer.hole_cards[1];
  if(first.rank === second.rank){ // check pair
    return minimalRaise();
  }else if(isSuited(myplayer.hole_cards)){
    return call();
  } else if(isHighCard(first) || isHighCard(second) || areContinous(first, second)) {
    return call();
  }else {
    return fold();
  }

}

function phase_two (){
  console.log('phase 2!');
  const allCards = gameState.community_cards.map(item => item);
  myplayer.hole_cards.forEach(item => allCards.push(item));
  console.log('allcards', allCards);

  const numberOfPairs = pairsWithCommunity(myplayer.hole_cards[0], myplayer.hole_cards[1], gameState.community_cards);
  if(numberOfPairs >= 2) {
    return allIn();
  } else if(numberOfPairs === 1) {
    return minimalRaise(); // TODO: maybe more?
  }

  if(isSuited(myplayer.hole_cards)) {
    const suit = myplayer.hole_cards[0].suit;
    const suited = gameState.community_cards.filter(card => {
        return card.suit === suit;
    }).length;

    if(suited === 3) { // FLUSH!
        return allIn();
    } else if(suited == 2) {
        if(gameState.community_cards.length < 5) { // flush still possible
            return minimalRaise();
        } // else use ranking
    }
  }

  // const communityOnly = getRanking(gameState.community_cards);
  const withOurCards = getRanking(allCards);
  return getRanking(allCards).then((rankingData) => {
    const allCardsRank = rankingData.rank;
    console.log('got rank', allCardsRank);
    if(allCardsRank >= 8) {
        return allIn();
    } else if(allCardsRank >= 5) {
        return minimalRaise();
    } else if(allCardsRank >= 3) {
        return minimalRaise();
    } else if(allCardsRank >= 2) {
        return minimalRaise();
    } else if(allCardsRank >= 1) {
        return call();
    } else {
        return fold();
    }
  }, err => {
    console.log('ERROR could not get rank', err);
    return call();
  });

  // const rank = evaluate(myplayer.hole_cards);
  // if(rank === 3){
  //   return gameState.minimum_raise;
  // }else if (rank ===2) {
  //   return call();
  // }
  // return fold();
}

function isHighCard(card) {
    const highCards = ['J', 'Q', 'A', 'K', '10'];
    return highCards.indexOf(card.rank.toUpperCase()) >= 0;
}

function isSmallBlind() {
    return gameState.current_buy_in === gameState.small_blind;
}

function callMax(max) {
    const called = call();
    return Math.min(max, called); // if "max" is selected, we fold
}

function isSuited(cards){
  const first = cards[0];
  const second = cards[1];
  if(first.suit === second.suit){
    return true;
  }
  return false;

}

function pairsWithCommunity(first, second, communityCards) {
    const pairs = communityCards.filter((commCard) => {
        return isPair(commCard, first) || isPair(commCard, second);
    });
    return pairs.length;
}

function isPair(first, second) {
    return first.rank === second.rank;
}

function areContinous(first, second) {
    const ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'];
    const firstValue = ranks.indexOf(first.rank);
    const secondValue = ranks.indexOf(second.rank);
    return ((firstValue + 1) == secondValue) || (firstValue == (secondValue + 1));
}

function call (){
  const c = gameState.current_buy_in - gameState.players[gameState.in_action].bet;
  return c;
}

function allIn(){
  const c = myplayer.stack;
  return c;
}

function fold(){
  return 0;
}

function minimalRaise() {
    const rand = Math.random();
    if(rand > 0.7) {
        return call() + rand * 10 * gameState.minimum_raise; // randomly higher
    } else {
        return call() + gameState.minimum_raise+100;
    }
}<commit_msg>error handling<commit_after>'use strict';

const getRanking = require('./ranking');

let gameState, myplayer;
module.exports = {
  VERSION: "It's a long way to the top",
  bet_request: function(game_state, bet) {
    new Promise((resolve, reject) => {
        gameState =  game_state;
        myplayer = game_state.players[game_state.in_action];
        console.log(myplayer.hole_cards);
        console.log(game_state);

        //Check for zero phase
        try {
            let promise;
            if(gameState.community_cards.length <= 3){
              promise = Promise.resolve(phase_zero());
            } else {
              promise = Promise.resolve(phase_two());
            }
            promise.then(resolve, reject);
        } catch(e) {
            console.error(e);
            reject(e);
        }
    }).then(value => {
        bet(Math.round(value));
    }).catch(err => {
        console.log('ERROR!!!! Bluffing', err);
        bet(Math.random() * myplayer.stack);
    });
  },
  showdown: function(game_state) {
  }
};

function phase_zero (){

  const highCards = myplayer.hole_cards.filter(isHighCard);
  if(highCards.length > 0 && isSmallBlind()) {
    console.log('we have a high card and it is still small blind - call!');
    return callMax(gameState.small_blind * 4);
  }
  const haveHighCard = highCards.length > 0;
  if(highCards.length > 1) {
    return minimalRaise();
  } else if(haveHighCard) {
    return callMax(4 * gameState.small_blind);
  }

  const first = myplayer.hole_cards[0];
  const second = myplayer.hole_cards[1];
  if(first.rank === second.rank){ // check pair
    return minimalRaise();
  }else if(isSuited(myplayer.hole_cards)){
    return call();
  } else if(isHighCard(first) || isHighCard(second) || areContinous(first, second)) {
    return call();
  }else {
    return fold();
  }

}

function phase_two (){
  console.log('phase 2!');
  const allCards = gameState.community_cards.map(item => item);
  myplayer.hole_cards.forEach(item => allCards.push(item));
  console.log('allcards', allCards);

  const numberOfPairs = pairsWithCommunity(myplayer.hole_cards[0], myplayer.hole_cards[1], gameState.community_cards);
  if(numberOfPairs >= 2) {
    return allIn();
  } else if(numberOfPairs === 1) {
    return minimalRaise(); // TODO: maybe more?
  }

  if(isSuited(myplayer.hole_cards)) {
    const suit = myplayer.hole_cards[0].suit;
    const suited = gameState.community_cards.filter(card => {
        return card.suit === suit;
    }).length;

    if(suited >= 3) { // FLUSH! TODO: change if they react
        return allIn();
    } else if(suited == 2) {
        if(gameState.community_cards.length < 5) { // flush still possible
            return minimalRaise();
        } // else use ranking
    }
  }

  // const communityOnly = getRanking(gameState.community_cards);
  const withOurCards = getRanking(allCards);
  return getRanking(allCards).then((rankingData) => {
    const allCardsRank = rankingData.rank;
    console.log('got rank', allCardsRank);
    if(allCardsRank >= 8) {
        return allIn();
    } else if(allCardsRank >= 5) {
        return minimalRaise();
    } else if(allCardsRank >= 3) {
        return minimalRaise();
    } else if(allCardsRank >= 2) {
        return minimalRaise();
    } else if(allCardsRank >= 1) {
        return call();
    } else {
        return fold();
    }
  }, err => {
    console.log('ERROR could not get rank', err);
    return call();
  });

  // const rank = evaluate(myplayer.hole_cards);
  // if(rank === 3){
  //   return gameState.minimum_raise;
  // }else if (rank ===2) {
  //   return call();
  // }
  // return fold();
}

function isHighCard(card) {
    const highCards = ['J', 'Q', 'A', 'K', '10'];
    return highCards.indexOf(card.rank.toUpperCase()) >= 0;
}

function isSmallBlind() {
    return gameState.current_buy_in === gameState.small_blind;
}

function callMax(max) {
    const called = call();
    return Math.min(max, called); // if "max" is selected, we fold
}

function isSuited(cards){
  const first = cards[0];
  const second = cards[1];
  if(first.suit === second.suit){
    return true;
  }
  return false;

}

function pairsWithCommunity(first, second, communityCards) {
    const pairs = communityCards.filter((commCard) => {
        return isPair(commCard, first) || isPair(commCard, second);
    });
    return pairs.length;
}

function isPair(first, second) {
    return first.rank === second.rank;
}

function areContinous(first, second) {
    const ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'];
    const firstValue = ranks.indexOf(first.rank);
    const secondValue = ranks.indexOf(second.rank);
    return ((firstValue + 1) == secondValue) || (firstValue == (secondValue + 1));
}

function call (){
  const c = gameState.current_buy_in - gameState.players[gameState.in_action].bet;
  return c;
}

function allIn(){
  const c = myplayer.stack;
  return c;
}

function fold(){
  return 0;
}

function minimalRaise() {
    const rand = Math.random();
    if(rand > 0.7) {
        return call() + rand * 10 * gameState.minimum_raise; // randomly higher
    } else {
        return call() + gameState.minimum_raise+100;
    }
}<|endoftext|>


<commit_before>/**
 * Parallel CasperJS runner, BDD flow, module-based tests, API helpers
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
/*global window:false, $:false*/
'use strict';

module.exports = {
  Conjure: Conjure,
  create: create,
  mixin: mixin,
  require: require // Allow tests to use component-land require.
};

var bddflow = require('bdd-flow');
var bind = require('bind');
var configurable = require('configurable.js');
var each = require('each');
var is = require('is');

/**
 * Allow test scripts to easily create common-case Conjure instances.
 *
 * @param {function} require CasperJS-env require()
 */
function create(require) {
  return new Conjure(require);
}

/**
 * Add BDD globals and init configuration.
 *
 * @param {function} require CasperJS-env require()
 */
function Conjure(require) {
  this.settings = {
    // Advertised.
    baseUrl: 'http://localhost:8174', // for url()
    initPath: '/', // 1st selector to wait for
    initSel: 'body', // 1st selector to wait for
    casperConfig: { // Directly passed to CasperJS create()
      exitOnError: true,
      logLevel: 'debug',
      pageSettings: {
        loadImages: false,
        loadPlugins: false,
        XSSAuditingEnabled: true,
        verbose: true,
        onError: function(self, m) { self.die('CasperJS onError: ' + m, 1); },
        onLoadError: function(self, m) { self.die('CasperJS onLoadError: ' + m, 1); }
      }
    },

    // Internal.
    cli: {}, // Native CasperJS CLI interface
    casperRequire: require // CasperJS-env require()
  };

  this.flow = bddflow.create();
}

configurable(Conjure.prototype);

/**
 * Perform last-minute init based on collected configuration.
 * Silently add an initial describe() to verify initial URL/selector.
 */
Conjure.prototype.test = function(name, cb) {
  var self = this;
  var cli = this.get('cli');

  if (cli.options.grep) { // Convert `--grep[v] foo bar baz` to /foo bar baz/
    this.flow.set('grep', new RegExp(cli.args.join(' ')));
  } else if (cli.options.grepv) {
    this.flow.set('grepv', new RegExp(cli.args.join(' ')));
  }

  this.casper = this.require('casper').create(this.get('casperConfig'));
  this.flow.addContextProp('casper', this.casper);
  Object.keys(thenContext).forEach(function(key) {
    self.flow.addContextProp(key, bind(self, self[key]));
  });

  this.flow.set('itWrap', function(name, cb) {
    self.casper.then(function() {
      cb.call(this);
    });
  });

  this.casper.start(this.url(this.get('initPath')));

  var descName = 'initial URL/selector';

  this.flow.addRootDescribe(descName, function() {
    this.it('should be loaded/found', function() {
      this.casper.then(function() {
        self.casper.waitForSelector(self.get('initSel'));
      });
    });
  });

  this.flow.addRootDescribe(name, cb);
  this.run();
};

/**
 * Convert a relative URL into a full.
 *
 * @param {string} relUrl Includes leading slash.
 * @return {string}
 */
Conjure.prototype.url = function(relUrl) {
  return this.get('baseUrl') + relUrl;
};

/**
 * Run collected BBD layers.
 */
Conjure.prototype.run = function() {
  var self = this;

  var initSel = this.get('initSel');
  var initPath = this.get('initPath');

  var initMsg = 'Opening [' + initPath + ']';
  if (initSel) {
    initMsg += ' Waiting For Selector [' + initSel + ']';
  }
  this.casper.test.info(initMsg);

  this.casper.then(function() {
    self.flow.run();
  });

  this.casper.run(function() {
    this.test.renderResults(true);
  });
};

/**
 * Methods mixed in to each it()/andThen() context.
 */
var thenContext = {};

/**
 * Wait for matching element to exist, then click it.
 *
 * @param {string} sel
 */
thenContext.andClick = function(sel) {
  this.selectorExists(sel);
  this.casper.thenEvaluate(function(sel) {
    $(sel).click();
  }, sel);
};

/**
 * then() wrapper that injections the same context as the outer it().
 *
 * @param {function} cb
 */
thenContext.andThen = function(cb) {
  var self = this;
  this.casper.then(function() {
    var targetContext = this;
    var keys = Object.keys(self).concat(Object.keys(thenContext));
    each(keys, function(key) {
      if (typeof self[key] === 'undefined') {
        if (is.Function(self[key])) {
          targetContext[key] = bind(self, self[key]);
        } else {
          targetContext[key] = self[key];
        }
      }
    });
    cb.call(targetContext);
  });
};

/**
 * assertTextExists() alternative that uses jQuery selectors.
 *
 * @param {string} sel
 * @param {string|regexp} text
 */
thenContext.assertSelText = function(sel, text) {
  this.casper.then(function() {
    this.test['assert' + (is.string(text) ? 'Equals' : 'Match')](
      this.evaluate(function(sel) {
        return $(sel).text();
      }, sel),
      text
    );
  });
};

/**
 * casper.each() alternative that injects the same context as the outer it().
 *
 * @param {array} list
 * @param {function} cb Receives (val).
 */
thenContext.forEach = function(list, cb) {
  var self = this;
  this.casper.each(list, function(__self, item) {
    cb.apply(self, [].slice.call(arguments, 1));
  });
};

/**
 * Append a fragment ID to the current URL.
 *
 * @param {string} hash Without leading '#'.
 * @param {string} [sel] Optional selector to wait for after navigation.
 */
thenContext.openHash = function(hash, sel) {
  this.casper.thenEvaluate(function _openHash(hash) {
    window.location.hash = '#' + hash;
  }, hash);
  if (sel) {
    this.selectorExists(sel);
  }
};

/**
 * Re-open the initial URL.
 */
thenContext.openInitUrl = function() {
  this.casper.thenOpen(this.url(this.get('initPath')));
};

/**
 * require() any file relative to --rootdir.
 *
 * @param {string} name Prefix with leading './'.
 *  If rootdir is /path/to/proj, './foo' will require /path/to/proj/foo.js.
 * @return {mixed} Loaded module.
 */
thenContext.require = function(name) {
  var require = this.get('casperRequire');
  var relPathRe = /^\.\//;
  if (relPathRe.test(name)) {
    return require(this.get('cli').options.rootdir + '/' + name.replace(relPathRe, ''));
  }
  return require(name); // Ex. 'casper' itself
};

/**
 * Alternative to waitForSelector() to use jQuery selector support,
 * ex. ':first' syntax.
 *
 * @param {string} sel
 * @param {boolean} [negate] Use true if selector is not expected to match.
 */
thenContext.selectorExists = function(sel, negate) {
  var self = this;
  this.casper.waitFor(function selectorExistsWaitFor() {
    return this.evaluate(function selectorExistsEvaluate(sel, count) {
      return count === $(sel).length;
    }, sel, negate ? 0 : 1);
  });
  this.casper.then(function selectorExistsThen() {
    this.test.assertTrue(true, (negate ? 'missing' : 'exists') + ': ' + sel);
  });
};

/**
 * Negated selectorExists().
 *
 * @param {string} sel
 */
thenContext.selectorMissing = function(sel) {
  this.selectorExists(sel, true);
};

/**
 * sendKeys() wrapper that first waits for a selector to exist.
 *
 * @param {string} sel
 * @param {string} keys
 */
thenContext.thenSendKeys = function(sel, keys) {
  this.selectorExists(sel);
  this.andThen(function() {
    this.sendKeys(sel, keys);
  });
};

mixin(thenContext);

/**
 * Mix the given function set into Conjure's prototype.
 *
 * @param {object} ext
 */
function mixin(ext) {
  Object.keys(ext).forEach(function(key) {
    if (typeof ext[key] === 'function') {
      Conjure.prototype[key] = ext[key];
    }
  });
}
<commit_msg>Move url() to thenContext mixin<commit_after>/**
 * Parallel CasperJS runner, BDD flow, module-based tests, API helpers
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
/*global window:false, $:false*/
'use strict';

module.exports = {
  Conjure: Conjure,
  create: create,
  mixin: mixin,
  require: require // Allow tests to use component-land require.
};

var bddflow = require('bdd-flow');
var bind = require('bind');
var configurable = require('configurable.js');
var each = require('each');
var is = require('is');

/**
 * Allow test scripts to easily create common-case Conjure instances.
 *
 * @param {function} require CasperJS-env require()
 */
function create(require) {
  return new Conjure(require);
}

/**
 * Add BDD globals and init configuration.
 *
 * @param {function} require CasperJS-env require()
 */
function Conjure(require) {
  this.settings = {
    // Advertised.
    baseUrl: 'http://localhost:8174', // for url()
    initPath: '/', // 1st selector to wait for
    initSel: 'body', // 1st selector to wait for
    casperConfig: { // Directly passed to CasperJS create()
      exitOnError: true,
      logLevel: 'debug',
      pageSettings: {
        loadImages: false,
        loadPlugins: false,
        XSSAuditingEnabled: true,
        verbose: true,
        onError: function(self, m) { self.die('CasperJS onError: ' + m, 1); },
        onLoadError: function(self, m) { self.die('CasperJS onLoadError: ' + m, 1); }
      }
    },

    // Internal.
    cli: {}, // Native CasperJS CLI interface
    casperRequire: require // CasperJS-env require()
  };

  this.flow = bddflow.create();
}

configurable(Conjure.prototype);

/**
 * Perform last-minute init based on collected configuration.
 * Silently add an initial describe() to verify initial URL/selector.
 */
Conjure.prototype.test = function(name, cb) {
  var self = this;
  var cli = this.get('cli');

  if (cli.options.grep) { // Convert `--grep[v] foo bar baz` to /foo bar baz/
    this.flow.set('grep', new RegExp(cli.args.join(' ')));
  } else if (cli.options.grepv) {
    this.flow.set('grepv', new RegExp(cli.args.join(' ')));
  }

  this.casper = this.require('casper').create(this.get('casperConfig'));
  this.flow.addContextProp('casper', this.casper);
  Object.keys(thenContext).forEach(function(key) {
    self.flow.addContextProp(key, bind(self, self[key]));
  });

  this.flow.set('itWrap', function(name, cb) {
    self.casper.then(function() {
      cb.call(this);
    });
  });

  this.casper.start(this.url(this.get('initPath')));

  var descName = 'initial URL/selector';

  this.flow.addRootDescribe(descName, function() {
    this.it('should be loaded/found', function() {
      this.casper.then(function() {
        self.casper.waitForSelector(self.get('initSel'));
      });
    });
  });

  this.flow.addRootDescribe(name, cb);
  this.run();
};

/**
 * Run collected BBD layers.
 */
Conjure.prototype.run = function() {
  var self = this;

  var initSel = this.get('initSel');
  var initPath = this.get('initPath');

  var initMsg = 'Opening [' + initPath + ']';
  if (initSel) {
    initMsg += ' Waiting For Selector [' + initSel + ']';
  }
  this.casper.test.info(initMsg);

  this.casper.then(function() {
    self.flow.run();
  });

  this.casper.run(function() {
    this.test.renderResults(true);
  });
};

/**
 * Methods mixed in to each it()/andThen() context.
 */
var thenContext = {};

/**
 * Wait for matching element to exist, then click it.
 *
 * @param {string} sel
 */
thenContext.andClick = function(sel) {
  this.selectorExists(sel);
  this.casper.thenEvaluate(function(sel) {
    $(sel).click();
  }, sel);
};

/**
 * then() wrapper that injections the same context as the outer it().
 *
 * @param {function} cb
 */
thenContext.andThen = function(cb) {
  var self = this;
  this.casper.then(function() {
    var targetContext = this;
    var keys = Object.keys(self).concat(Object.keys(thenContext));
    each(keys, function(key) {
      if (typeof self[key] === 'undefined') {
        if (is.Function(self[key])) {
          targetContext[key] = bind(self, self[key]);
        } else {
          targetContext[key] = self[key];
        }
      }
    });
    cb.call(targetContext);
  });
};

/**
 * assertTextExists() alternative that uses jQuery selectors.
 *
 * @param {string} sel
 * @param {string|regexp} text
 */
thenContext.assertSelText = function(sel, text) {
  this.casper.then(function() {
    this.test['assert' + (is.string(text) ? 'Equals' : 'Match')](
      this.evaluate(function(sel) {
        return $(sel).text();
      }, sel),
      text
    );
  });
};

/**
 * casper.each() alternative that injects the same context as the outer it().
 *
 * @param {array} list
 * @param {function} cb Receives (val).
 */
thenContext.forEach = function(list, cb) {
  var self = this;
  this.casper.each(list, function(__self, item) {
    cb.apply(self, [].slice.call(arguments, 1));
  });
};

/**
 * Append a fragment ID to the current URL.
 *
 * @param {string} hash Without leading '#'.
 * @param {string} [sel] Optional selector to wait for after navigation.
 */
thenContext.openHash = function(hash, sel) {
  this.casper.thenEvaluate(function _openHash(hash) {
    window.location.hash = '#' + hash;
  }, hash);
  if (sel) {
    this.selectorExists(sel);
  }
};

/**
 * Re-open the initial URL.
 */
thenContext.openInitUrl = function() {
  this.casper.thenOpen(this.url(this.get('initPath')));
};

/**
 * require() any file relative to --rootdir.
 *
 * @param {string} name Prefix with leading './'.
 *  If rootdir is /path/to/proj, './foo' will require /path/to/proj/foo.js.
 * @return {mixed} Loaded module.
 */
thenContext.require = function(name) {
  var require = this.get('casperRequire');
  var relPathRe = /^\.\//;
  if (relPathRe.test(name)) {
    return require(this.get('cli').options.rootdir + '/' + name.replace(relPathRe, ''));
  }
  return require(name); // Ex. 'casper' itself
};

/**
 * Alternative to waitForSelector() to use jQuery selector support,
 * ex. ':first' syntax.
 *
 * @param {string} sel
 * @param {boolean} [negate] Use true if selector is not expected to match.
 */
thenContext.selectorExists = function(sel, negate) {
  var self = this;
  this.casper.waitFor(function selectorExistsWaitFor() {
    return this.evaluate(function selectorExistsEvaluate(sel, count) {
      return count === $(sel).length;
    }, sel, negate ? 0 : 1);
  });
  this.casper.then(function selectorExistsThen() {
    this.test.assertTrue(true, (negate ? 'missing' : 'exists') + ': ' + sel);
  });
};

/**
 * Negated selectorExists().
 *
 * @param {string} sel
 */
thenContext.selectorMissing = function(sel) {
  this.selectorExists(sel, true);
};

/**
 * sendKeys() wrapper that first waits for a selector to exist.
 *
 * @param {string} sel
 * @param {string} keys
 */
thenContext.thenSendKeys = function(sel, keys) {
  this.selectorExists(sel);
  this.andThen(function() {
    this.sendKeys(sel, keys);
  });
};

/**
 * Convert a relative URL into a full.
 *
 * @param {string} relUrl Includes leading slash.
 * @return {string}
 */
thenContext.url = function(relUrl) {
  return this.get('baseUrl') + relUrl;
};

mixin(thenContext);

/**
 * Mix the given function set into Conjure's prototype.
 *
 * @param {object} ext
 */
function mixin(ext) {
  Object.keys(ext).forEach(function(key) {
    if (typeof ext[key] === 'function') {
      Conjure.prototype[key] = ext[key];
    }
  });
}
<|endoftext|>