<commit_before>/*
 Copyright 2016 - 2018 by Jan Dockx

 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 ContractError = require('./ContractError')
const is = require('../_private/is')
const property = require('../_private/property')
const stack = require('../_private/stack')
const report = require('../_private/report')
const assert = require('assert')

const namePrefix = '𝕋⚖'

// noinspection ParameterNamingConventionJS
/**
 * Abstract definition of a function contract.
 *
 * An AbstractContract consists of an array of preconditions, an array of nominal postconditions,
 * and an array of exceptional postconditions.
 *
 * The conditions are functions whose result is interpreted as a booleany value.
 * The conditions are called with the same `this` and arguments as the functional call in which they are
 * verified. When verifying nominal postconditions, the result of the function call is added as extra argument.
 * When verifying exceptional postconditions, the exception thrown by the function call is added as extra argument.
 * Finally, a version of the contract function bound to `this` is supplied as final parameter when verifying
 * nominal and exceptional postconditions. This function reference can be used in contracts that use recursion.
 *
 * Furthermore, an instance contains a `location` property, which is a line of text
 * that refers to the source code where the contract was created. For internal contracts, this is
 * `AbstractContract.internalLocation.
 *
 * If `verify` and `verifyPostconditions` are both truthy, contract function verification will verify preconditions,
 * postconditions and exception conditions. If `verify` is truthy, but `verifyPostconditions` is falsy, contract
 * function verification will verify preconditions, but not postconditions and exception conditions. This is the
 * default. If `verify` is falsy, contract function executions will not be verified.
 *
 * The `contract` of a contract function is a separate object that has the contract it is an implementation of as a
 * prototype. Therefor, the `verify` and `verifyPostconditions` properties can be overridden for all
 * `AbstractContracts` by changing the properties of `AbstractContracts.prototype`, for one contract by changing its
 * properties, or for a particular contract function `cf` by changing the properties of `cf.contract`. The values
 * the properties hold at the moment of the call are used (this is relevant for asynchronous functions).
 *
 * With well-tested code, the default settings should be used in production. When the code is extremely stable,
 * `verify` can be set to `false` to gain additional speed. In tests, `verify` should be truthy and
 * `verifyPostconditions` should be `true`, at least for the function under test.
 *
 * The `_location` argument is for internal use, and might be removed.
 *
 * @constructor
 */
function AbstractContract (kwargs, /* Object? */ _location) {
  assert.ok(kwargs)
  assert(!kwargs.pre || Array.isArray(kwargs.pre), 'optional kwargs.pre is an array')
  assert(!kwargs.post || Array.isArray(kwargs.post), 'optional kwargs.post is an array')
  assert(!kwargs.exception || Array.isArray(kwargs.exception), 'optional kwargs.exception is an array')
  assert(!_location || _location === AbstractContract.internalLocation || typeof _location === 'string', 'optional private _location is internal or a string')

  const self = this

  /* This cannot be defined in the prototype. The `self` is the contract, not the `this`. When this function is called
     as a method of a random object, that random object is the `this`, not this contract. */
  function abstract () { throw new AbstractContract.AbstractError(self, stack.raw()) }

  const location = _location || stack.location(1)
  AbstractContract.bless(abstract, self, abstract, location)
  property.setAndFreeze(self, '_pre', Object.freeze(kwargs.pre ? kwargs.pre.slice() : []))
  property.setAndFreeze(self, '_post', Object.freeze(kwargs.post ? kwargs.post.slice() : []))
  property.setAndFreeze(self, '_exception', Object.freeze(kwargs.exception ? kwargs.exception.slice() : []))
  property.setAndFreeze(self, 'location', Object.freeze(location))
  property.setAndFreeze(self, 'abstract', abstract)
}

/**
 * Object to be used as location for contracts and implementations that are generated inside this library.
 */
AbstractContract.internalLocation = Object.freeze({
  toString: function () { return 'INTERNAL' }
})

AbstractContract.prototype = {
  constructor: AbstractContract,
  _pre: null,
  _post: null,
  _exception: null,
  isImplementedBy: function (f) {
    return AbstractContract.isAGeneralContractFunction(f) && f.contract === this
  }
}
property.frozenReadOnlyArray(AbstractContract.prototype, 'pre', '_pre')
property.frozenReadOnlyArray(AbstractContract.prototype, 'post', '_post')
property.frozenReadOnlyArray(AbstractContract.prototype, 'exception', '_exception')
property.setAndFreeze(AbstractContract.prototype, 'location', AbstractContract.internalLocation)
property.setAndFreeze(AbstractContract.prototype, 'abstract', null)

AbstractContract.namePrefix = namePrefix

/**
 * This function is intended to be used as the bind function of contract functions. It makes sure
 * that, when applied to a contract function, the result
 * [is also a contract function]{@linkplain AbstractContract#isAContractFunction}.
 * The bind aspect of the functionality is the same as {@link Function#prototype#bind}.
 * The implementation of the resulting contract function is also bound in the same
 * way as the resulting contract function itself.
 */
AbstractContract.bindContractFunction = function bind () {
  assert(AbstractContract.isAGeneralContractFunction(this), 'this is a general contract function')

  const bound = Function.prototype.bind.apply(this, arguments)
  const boundImplementation = Function.prototype.bind.apply(this.implementation, arguments)
  AbstractContract.bless(bound, this.contract, boundImplementation, this.location)
  return bound
}

/**
 * A General Contract Function is an implementation of an AbstractContract. This function verifies whether a function
 * given as a parameter is a General Contract Function.
 *
 * To be a General Contract Function, the subject must
 *

 *
be a function,

 *
have a frozen `contract` property that refers to a AbstractContract,

 *
have a frozen `implementation` property that refers to a function (which realizes the contract),

 *
have a frozen `location` property, that has a value,

 *
have a frozen `bind` property, which is {@link AbstractContract.bindContractFunction}, and

 *
have a `name`, which is a string that gives information for a programmer to understand which contract
 *     function this is, and

 *
if the `implementation` function has a `prototype`, have a `prototype` property,
 *

 *
that is an object,

 *
that has a `constructor` property that is the contract function, and

 *
that has `f.implementation.prototype` in its prototype chain, or is equal to it.
 *

 *

 */
AbstractContract.isAGeneralContractFunction = function (f) {
  // Apart from this, we expect f to have a name. But it is controlled by the JavaScript engine, and we cannot
  // freeze it, and not guaranteed in all engines.
  return typeof f === 'function' &&
         is.frozenOwnProperty(f, 'contract') &&
         f.contract instanceof AbstractContract &&
         is.frozenOwnProperty(f, 'implementation') &&
         typeof f.implementation === 'function' &&
         is.frozenOwnProperty(f, 'location') &&
         f.location &&
         (f === f.implementation ||
            f.name === report.conciseCondition(AbstractContract.namePrefix, f.implementation)) &&
         is.frozenOwnProperty(f, 'bind') &&
         f.bind === AbstractContract.bindContractFunction &&
         (!f.implementation.hasOwnProperty('prototype') ||
             (typeof f.prototype === 'object' &&
                 f.prototype.constructor === f &&
                 (f.prototype === f.implementation.prototype || f.prototype instanceof f.implementation)))
}

/**
 * A Contract Function is an implementation of a Contract. This function verifies whether a function
 * given as a parameter is a Contract Function.
 *
 * To be a Contract Function, the subject must
 *

 *
be a [general contract function]{@linkplain #isAGeneralContractFunction()},

 *
have a frozen `location` property, which is a string that represents a location in source code,
 *     outside this library.

 *

 */
AbstractContract.isAContractFunction = function (f) {
  return AbstractContract.isAGeneralContractFunction(f) && is.stackLocation(f.location)
}

/**
 * Helper function that transforms any function given as contractFunction
 * into a [contract function]{@linkplain AbstractContract#isAContractFunction}
 * for the given parameters.
 * If {@code implFunction.prototype} exists, the {@code contractFunction.prototype} is changed to
 * an object that refers to {@code contractFunction} as {@code contractFunction.prototype.constructor},
 * is otherwise empty, and has {@code implFunction.prototype} as prototype.
 *
 * @param contractFunction {Function} the regular {Function} to be transformed into a contract function
 * @param contract {AbstractContract} the contract contractFunction is a realisation of
 * @param implFunction {Function} the function that is used in contractFunction
 *                     to realize the postconditions of contract under its preconditions
 * @param location {String} the location outside this library that the resulting
 *                          [contract function]{@linkplain AbstractContract#isAContractFunction} will carry,
 *                          that says where it is defined.
 */
AbstractContract.bless = function bless (contractFunction, contract, implFunction, location) {
  assert.equal(typeof contractFunction, 'function')
  // noinspection JSUnresolvedVariable
  assert.ok(!contractFunction.contract)
  // noinspection JSUnresolvedVariable
  assert.ok(!contractFunction.implementation)
  // noinspection JSUnresolvedVariable
  assert.ok(!contractFunction.location)
  assert.strictEqual(contractFunction.bind, Function.prototype.bind)
  assert(contract instanceof AbstractContract, 'contract is an AbstractContract')
  assert.equal(typeof implFunction, 'function')
  assert(location === AbstractContract.internalLocation || is.stackLocation(location), 'location is internal, or a stack location')

  property.setAndFreeze(contractFunction, 'contract', contract)
  property.setAndFreeze(contractFunction, 'implementation', implFunction)
  property.setAndFreeze(contractFunction, 'location', location)
  property.setAndFreeze(contractFunction, 'bind', AbstractContract.bindContractFunction)
  if (implFunction.hasOwnProperty('prototype')) {
    contractFunction.prototype = Object.create(implFunction.prototype)
    property.setAndFreeze(contractFunction.prototype, 'constructor', contractFunction)
  }
  /* The name of the contract function will always be 'contractFunction', because we need to define it in
    `Contract.implementation`, because we need to refer to the contract function internally. We would like the result
    of `Contract.implementation` to get a name inferred from its syntactic position, but cannot happen: before
    we reach the 'syntactic position' (a.k.a, we assign the contract function to a variable or property with
    a name), it will already have the name `contractFunction` we need internally. Therefor, we will explicitly set
    the name, based on the name of implementation function.
    The Firefox feature `displayName` will not be used.  */
  // IDEA we might also add a name property to a Contract, and combine it with that
  if (contractFunction !== implFunction) {
    /* `abstract` refers to itself as implementation; we do not change its name (it would create a circular name
       definition) */
    // IDEA defend code against more complex circular structure
    property.frozenDerived(
      contractFunction,
      'name',
      report.conciseCondition.bind(null, namePrefix, implFunction)
    )
  }
}

/**
 * Function that always returns false.
 */
AbstractContract.falseCondition = function () { return false }

/**
 * Singleton array of {@linkplain AbstractContract#falseCondition}. Can be used the clearly signal
 * that a function should never throw exceptions, or never end nominally, or should never be called,
 * because the preconditions will always fail.
 */
AbstractContract.mustNotHappen = [AbstractContract.falseCondition]

/**
 * The most general function AbstractContract. This has the most strict preconditions (nothing is allowed), which can
 * be weakened by specializations, and the most general nominal and exceptional postconditions (anything goes),
 * which can be strengthened by specializations.
 */
AbstractContract.root = new AbstractContract(
  {
    pre: AbstractContract.mustNotHappen,
    post: [],
    exception: []
  },
  AbstractContract.internalLocation
)

const message = 'an abstract function cannot be executed'

/**
 * Thrown when an abstract method is called. You shouldn't.
 *
 * @constructor
 */
function AbstractError (contract, rawStack) {
  assert(contract instanceof AbstractContract, 'contract is an AbstractContract')
  assert(is.stack(rawStack), 'rawStack is a stack')

  ContractError.call(this, rawStack)
  property.setAndFreeze(this, 'name', AbstractError.name)
  property.setAndFreeze(this, 'message', message)
  property.setAndFreeze(this, 'contract', contract)
}

AbstractError.prototype = new ContractError(stack.raw())
AbstractError.prototype.constructor = AbstractError
property.setAndFreeze(AbstractError.prototype, 'name', AbstractError.name)
property.setAndFreeze(AbstractError.prototype, 'message', message)
property.setAndFreeze(AbstractError.prototype, 'contract', null)

AbstractError.message = message

AbstractContract.AbstractError = AbstractError

module.exports = AbstractContract
<commit_msg>Add verify and verifyPostconditions properties to AbstractContract; bless with a new contract object that has the contract as prototype<commit_after>/*
 Copyright 2016 - 2018 by Jan Dockx

 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 ContractError = require('./ContractError')
const is = require('../_private/is')
const property = require('../_private/property')
const stack = require('../_private/stack')
const report = require('../_private/report')
const assert = require('assert')

const namePrefix = '𝕋⚖'

// noinspection ParameterNamingConventionJS
/**
 * Abstract definition of a function contract.
 *
 * An AbstractContract consists of an array of preconditions, an array of nominal postconditions,
 * and an array of exceptional postconditions.
 *
 * The conditions are functions whose result is interpreted as a booleany value.
 * The conditions are called with the same `this` and arguments as the functional call in which they are
 * verified. When verifying nominal postconditions, the result of the function call is added as extra argument.
 * When verifying exceptional postconditions, the exception thrown by the function call is added as extra argument.
 * Finally, a version of the contract function bound to `this` is supplied as final parameter when verifying
 * nominal and exceptional postconditions. This function reference can be used in contracts that use recursion.
 *
 * Furthermore, an instance contains a `location` property, which is a line of text
 * that refers to the source code where the contract was created. For internal contracts, this is
 * `AbstractContract.internalLocation.
 *
 * If `verify` and `verifyPostconditions` are both truthy, contract function verification will verify preconditions,
 * postconditions and exception conditions. If `verify` is truthy, but `verifyPostconditions` is falsy, contract
 * function verification will verify preconditions, but not postconditions and exception conditions. This is the
 * default. If `verify` is falsy, contract function executions will not be verified.
 *
 * The `contract` of a contract function is a separate object that has the contract it is an implementation of as a
 * prototype. Therefor, the `verify` and `verifyPostconditions` properties can be overridden for all
 * `AbstractContracts` by changing the properties of `AbstractContracts.prototype`, for one contract by changing its
 * properties, or for a particular contract function `cf` by changing the properties of `cf.contract`. The values
 * the properties hold at the moment of the call are used (this is relevant for asynchronous functions).
 *
 * With well-tested code, the default settings should be used in production. When the code is extremely stable,
 * `verify` can be set to `false` to gain additional speed. In tests, `verify` should be truthy and
 * `verifyPostconditions` should be `true`, at least for the function under test.
 *
 * The `_location` argument is for internal use, and might be removed.
 *
 * @constructor
 */
function AbstractContract (kwargs, /* Object? */ _location) {
  assert.ok(kwargs)
  assert(!kwargs.pre || Array.isArray(kwargs.pre), 'optional kwargs.pre is an array')
  assert(!kwargs.post || Array.isArray(kwargs.post), 'optional kwargs.post is an array')
  assert(!kwargs.exception || Array.isArray(kwargs.exception), 'optional kwargs.exception is an array')
  assert(!_location || _location === AbstractContract.internalLocation || typeof _location === 'string', 'optional private _location is internal or a string')

  const self = this

  /* This cannot be defined in the prototype. The `self` is the contract, not the `this`. When this function is called
     as a method of a random object, that random object is the `this`, not this contract. */
  function abstract () { throw new AbstractContract.AbstractError(self, stack.raw()) }

  const location = _location || stack.location(1)
  AbstractContract.bless(abstract, self, abstract, location)
  property.setAndFreeze(self, '_pre', Object.freeze(kwargs.pre ? kwargs.pre.slice() : []))
  property.setAndFreeze(self, '_post', Object.freeze(kwargs.post ? kwargs.post.slice() : []))
  property.setAndFreeze(self, '_exception', Object.freeze(kwargs.exception ? kwargs.exception.slice() : []))
  property.setAndFreeze(self, 'location', Object.freeze(location))
  property.setAndFreeze(self, 'abstract', abstract)
}

/**
 * Object to be used as location for contracts and implementations that are generated inside this library.
 */
AbstractContract.internalLocation = Object.freeze({
  toString: function () { return 'INTERNAL' }
})

AbstractContract.prototype = {
  constructor: AbstractContract,
  _pre: null,
  _post: null,
  _exception: null,
  isImplementedBy: function (f) {
    return AbstractContract.isAGeneralContractFunction(f) && f.contract === this
  }
}
property.frozenReadOnlyArray(AbstractContract.prototype, 'pre', '_pre')
property.frozenReadOnlyArray(AbstractContract.prototype, 'post', '_post')
property.frozenReadOnlyArray(AbstractContract.prototype, 'exception', '_exception')
property.setAndFreeze(AbstractContract.prototype, 'location', AbstractContract.internalLocation)
property.setAndFreeze(AbstractContract.prototype, 'abstract', null)
AbstractContract.prototype.verify = true
AbstractContract.prototype.verifyPostconditions = false

AbstractContract.namePrefix = namePrefix

/**
 * This function is intended to be used as the bind function of contract functions. It makes sure
 * that, when applied to a contract function, the result
 * [is also a contract function]{@linkplain AbstractContract#isAContractFunction}.
 * The bind aspect of the functionality is the same as {@link Function#prototype#bind}.
 * The implementation of the resulting contract function is also bound in the same
 * way as the resulting contract function itself.
 */
AbstractContract.bindContractFunction = function bind () {
  assert(AbstractContract.isAGeneralContractFunction(this), 'this is a general contract function')

  const bound = Function.prototype.bind.apply(this, arguments)
  const boundImplementation = Function.prototype.bind.apply(this.implementation, arguments)
  AbstractContract.bless(bound, Object.create(this.contract), boundImplementation, this.location)
  return bound
}

/**
 * A General Contract Function is an implementation of an AbstractContract. This function verifies whether a function
 * given as a parameter is a General Contract Function.
 *
 * To be a General Contract Function, the subject must
 *

 *
be a function,

 *
have a frozen `contract` property that refers to a AbstractContract,

 *
have a frozen `implementation` property that refers to a function (which realizes the contract),

 *
have a frozen `location` property, that has a value,

 *
have a frozen `bind` property, which is {@link AbstractContract.bindContractFunction}, and

 *
have a `name`, which is a string that gives information for a programmer to understand which contract
 *     function this is, and

 *
if the `implementation` function has a `prototype`, have a `prototype` property,
 *

 *
that is an object,

 *
that has a `constructor` property that is the contract function, and

 *
that has `f.implementation.prototype` in its prototype chain, or is equal to it.
 *

 *

 */
AbstractContract.isAGeneralContractFunction = function (f) {
  // Apart from this, we expect f to have a name. But it is controlled by the JavaScript engine, and we cannot
  // freeze it, and not guaranteed in all engines.
  return typeof f === 'function' &&
         is.frozenOwnProperty(f, 'contract') &&
         f.contract instanceof AbstractContract &&
         is.frozenOwnProperty(f, 'implementation') &&
         typeof f.implementation === 'function' &&
         is.frozenOwnProperty(f, 'location') &&
         f.location &&
         (f === f.implementation ||
            f.name === report.conciseCondition(AbstractContract.namePrefix, f.implementation)) &&
         is.frozenOwnProperty(f, 'bind') &&
         f.bind === AbstractContract.bindContractFunction &&
         (!f.implementation.hasOwnProperty('prototype') ||
             (typeof f.prototype === 'object' &&
                 f.prototype.constructor === f &&
                 (f.prototype === f.implementation.prototype || f.prototype instanceof f.implementation)))
}

/**
 * A Contract Function is an implementation of a Contract. This function verifies whether a function
 * given as a parameter is a Contract Function.
 *
 * To be a Contract Function, the subject must
 *

 *
be a [general contract function]{@linkplain #isAGeneralContractFunction()},

 *
have a frozen `location` property, which is a string that represents a location in source code,
 *     outside this library.

 *

 */
AbstractContract.isAContractFunction = function (f) {
  return AbstractContract.isAGeneralContractFunction(f) && is.stackLocation(f.location)
}

/**
 * Helper function that transforms any function given as contractFunction
 * into a [contract function]{@linkplain AbstractContract#isAContractFunction}
 * for the given parameters.
 * If {@code implFunction.prototype} exists, the {@code contractFunction.prototype} is changed to
 * an object that refers to {@code contractFunction} as {@code contractFunction.prototype.constructor},
 * is otherwise empty, and has {@code implFunction.prototype} as prototype.
 *
 * @param contractFunction {Function} the regular {Function} to be transformed into a contract function
 * @param contract {AbstractContract} the contract contractFunction is a realisation of
 * @param implFunction {Function} the function that is used in contractFunction
 *                     to realize the postconditions of contract under its preconditions
 * @param location {String} the location outside this library that the resulting
 *                          [contract function]{@linkplain AbstractContract#isAContractFunction} will carry,
 *                          that says where it is defined.
 */
AbstractContract.bless = function bless (contractFunction, contract, implFunction, location) {
  assert.equal(typeof contractFunction, 'function')
  // noinspection JSUnresolvedVariable
  assert.ok(!contractFunction.contract)
  // noinspection JSUnresolvedVariable
  assert.ok(!contractFunction.implementation)
  // noinspection JSUnresolvedVariable
  assert.ok(!contractFunction.location)
  assert.strictEqual(contractFunction.bind, Function.prototype.bind)
  assert(contract instanceof AbstractContract, 'contract is an AbstractContract')
  assert.equal(typeof implFunction, 'function')
  assert(location === AbstractContract.internalLocation || is.stackLocation(location), 'location is internal, or a stack location')

  property.setAndFreeze(contractFunction, 'contract', Object.create(contract))
  property.setAndFreeze(contractFunction, 'implementation', implFunction)
  property.setAndFreeze(contractFunction, 'location', location)
  property.setAndFreeze(contractFunction, 'bind', AbstractContract.bindContractFunction)
  if (implFunction.hasOwnProperty('prototype')) {
    contractFunction.prototype = Object.create(implFunction.prototype)
    property.setAndFreeze(contractFunction.prototype, 'constructor', contractFunction)
  }
  /* The name of the contract function will always be 'contractFunction', because we need to define it in
    `Contract.implementation`, because we need to refer to the contract function internally. We would like the result
    of `Contract.implementation` to get a name inferred from its syntactic position, but cannot happen: before
    we reach the 'syntactic position' (a.k.a, we assign the contract function to a variable or property with
    a name), it will already have the name `contractFunction` we need internally. Therefor, we will explicitly set
    the name, based on the name of implementation function.
    The Firefox feature `displayName` will not be used.  */
  // IDEA we might also add a name property to a Contract, and combine it with that
  if (contractFunction !== implFunction) {
    /* `abstract` refers to itself as implementation; we do not change its name (it would create a circular name
       definition) */
    // IDEA defend code against more complex circular structure
    property.frozenDerived(
      contractFunction,
      'name',
      report.conciseCondition.bind(null, namePrefix, implFunction)
    )
  }
}

/**
 * Function that always returns false.
 */
AbstractContract.falseCondition = function () { return false }

/**
 * Singleton array of {@linkplain AbstractContract#falseCondition}. Can be used the clearly signal
 * that a function should never throw exceptions, or never end nominally, or should never be called,
 * because the preconditions will always fail.
 */
AbstractContract.mustNotHappen = [AbstractContract.falseCondition]

/**
 * The most general function AbstractContract. This has the most strict preconditions (nothing is allowed), which can
 * be weakened by specializations, and the most general nominal and exceptional postconditions (anything goes),
 * which can be strengthened by specializations.
 */
AbstractContract.root = new AbstractContract(
  {
    pre: AbstractContract.mustNotHappen,
    post: [],
    exception: []
  },
  AbstractContract.internalLocation
)

const message = 'an abstract function cannot be executed'

/**
 * Thrown when an abstract method is called. You shouldn't.
 *
 * @constructor
 */
function AbstractError (contract, rawStack) {
  assert(contract instanceof AbstractContract, 'contract is an AbstractContract')
  assert(is.stack(rawStack), 'rawStack is a stack')

  ContractError.call(this, rawStack)
  property.setAndFreeze(this, 'name', AbstractError.name)
  property.setAndFreeze(this, 'message', message)
  property.setAndFreeze(this, 'contract', contract)
}

AbstractError.prototype = new ContractError(stack.raw())
AbstractError.prototype.constructor = AbstractError
property.setAndFreeze(AbstractError.prototype, 'name', AbstractError.name)
property.setAndFreeze(AbstractError.prototype, 'message', message)
property.setAndFreeze(AbstractError.prototype, 'contract', null)

AbstractError.message = message

AbstractContract.AbstractError = AbstractError

module.exports = AbstractContract
<|endoftext|>


<commit_before>/**
 * json
 *
 * @param {Object} data
 * @param {Object[]} data.messages
 * @return {String}
 */
exports.json = function (data) {
  return JSON.stringify(data);
}

/**
 * pretty
 *
 * @param {Object} data
 * @param {Object[]} data.messages
 * @return {String}
 */
exports.pretty = function (data) {
  return JSON.stringify(data, null, ' ');
};

/**
 * vim
 *
 * @param {Object} data
 * @param {Object[]} data.messages
 * @return {String}
 */
exports.vim = function (data) {
  if (!data || !data.messages) {
    return '';
  }

  return data.messages.map(function (m) {
    return [
      m.file,
      m.from.line + '.' + m.from.ch,
      m.severity,
      m.message,
    ].join(': ');
  }).join('\n');
};
<commit_msg>use colon only<commit_after>/**
 * json
 *
 * @param {Object} data
 * @param {Object[]} data.messages
 * @return {String}
 */
exports.json = function (data) {
  return JSON.stringify(data);
}

/**
 * pretty
 *
 * @param {Object} data
 * @param {Object[]} data.messages
 * @return {String}
 */
exports.pretty = function (data) {
  return JSON.stringify(data, null, ' ');
};

/**
 * vim
 *
 * @param {Object} data
 * @param {Object[]} data.messages
 * @return {String}
 */
exports.vim = function (data) {
  if (!data || !data.messages) {
    return '';
  }

  return data.messages.map(function (m) {
    return [
      m.file,
      (m.from.line - 1) + ':' + (m.from.ch),
      m.severity,
      m.message,
    ].join(': ');
  }).join('\n');
};
<|endoftext|>


<commit_before>var itunes = require('playback');
var fs = require('fs');
var gui = require('nw.gui');
var win = gui.Window.get();
var app = gui.App;
var np = { };
var lyricsProviders = (function() {
    var obj = require('./lyricsProviders.js');
    var arr = new Array();
    $.each(obj, function(name, item) {
        arr.push(item);
    });
    return arr;
})();
var lyrics_dir = process.env['HOME']+'/.lyrics';
forceRefresh = false;

$(document).ready(function() {
   NRdiv = $('#iTunesNotRunning');
   lyricsDiv = $('#lyrics');
   headerDiv = $('#header');
   loaderDiv = $('#loader');
   noLyricsDiv = $('#NoLyricsFound');
   itunes.currentTrack();
});

win.on('close', function(event) {
    if(event=="quit") {
        win.close(true);
    }
    else{
        this.hide();
    }
});
app.on('reopen', function() {win.show(); win.focus()})
itunes.on('playing', function(data) {
   if(!data) {
        NRdiv.show();
        lyricsDiv.hide();
        headerDiv.hide();
        loaderDiv.hide();
        return;
   }
   if(forceRefresh) {setCurrentTrack(data.artist, data.title); forceRefresh=false;}
   checkIfNewSong(data.artist, data.name, function (artist, title) {
       setCurrentTrack(artist, title);
   });
})

win.on('enter-fullscreen', function() {$("html *").addClass('fullscreen'); lyricsDiv.hide(); setTimeout(function() {lyricsDiv.show();}, 0);});
win.on('leave-fullscreen', function() {$("html *").removeClass('fullscreen'); lyricsDiv.hide(); setTimeout(function() {lyricsDiv.show();}, 0);});
window.addEventListener('resize', function(event){
    autoSizeText($('#title')[0]);
    autoSizeText($('#artist')[0]);
});

$(document).keydown(function(evt) {
    if ((evt.which == '115' || evt.which == '83' ) && (evt.ctrlKey || evt.metaKey)) // Cmd+S
        {
            evt.preventDefault();
            lyricsDiv.removeClass('editmode');
            lyricsDiv.removeAttr('contenteditable');
            var lyrics = lyricsDiv[0].innerText;
            var artist = np.artist.replace(/ /g, "_"); var title = np.title.replace(/ /g, "_")
            saveLyrics(artist, title, lyrics);
            return false;
        }
    if (evt.keyCode == 27) { // Escape
            evt.preventDefault();
            lyricsDiv.removeClass('editmode');
            lyricsDiv.removeAttr('contenteditable');
            var artist = np.artist.replace(/ /g, "_"); var title = np.title.replace(/ /g, "_")
            toggleSearch(false);
            readLyrics(artist, title);
    }
    var tag = evt.target.tagName.toLowerCase();
    if (tag != 'input' && tag != 'textarea' && evt.target.getAttribute('contenteditable') != 'true') {
        if (String.fromCharCode(evt.keyCode) == "R") {
            forceRefresh = true;
            itunes.currentTrack();
        }
        if (String.fromCharCode(evt.keyCode) == "D") {
            require('nw.gui').Window.get().showDevTools()
        }
        if (String.fromCharCode(evt.keyCode) == "S") {
            toggleSearch();
        }
        if (String.fromCharCode(evt.keyCode) == "E") {
            editMode();
        }
    };
});

function autoSizeText(el) {
    el.style.fontSize = null;
    function resizeText() {
        var style = window.getComputedStyle(el);
        var elNewFontSize = (parseInt(style.getPropertyValue('font-size').slice(0,-2)) -1) + 'px';
        el.style.fontSize = elNewFontSize;
    }
    while (el.offsetWidth+50 > window.innerWidth) { resizeText(); }
}

function editMode(focus) {
    noLyricsDiv.hide();
    lyricsDiv.show();
    lyricsDiv.addClass("editmode");
    lyricsDiv.attr('contenteditable', "true");
    if(focus) { lyricsDiv.focus(); }
}

function markAsInstrumental(artist, title) {
    var artist = artist || np.artist;
    var title = title || np.title;
    saveLyrics(artist, title, "Instrumental");
    setLyrics('Instrumental');
    noLyricsDiv.hide();
    lyricsDiv.show();
}

function webSearch(artist, title) {
    var artist = artist || np.artist;
    var title = title || np.title;
    var query = artist + ' ' + title + ' lyrics';
    gui.Shell.openExternal('http://google.com/search?q='+encodeURIComponent(query));
}

function onSearch(e) {
    if (!e) e = window.event;
    if (e.keyCode == '13') {
        var aBox = $('#searchArtist');
        var tBox = $('#searchTitle');
        var artist = aBox.val();
        var title = tBox.val();
        toggleSearch();
        setCurrentTrack(artist, title);
    };
};

$('#searchArtist').keypress(onSearch);
$('#searchTitle').keypress(onSearch);

$('#header').dblclick(function() {
    var aBox = $('#searchArtist');
    var tBox = $('#searchTitle');
    aBox.val(np.artist);
    tBox.val(np.title);
    toggleSearch();
});

function toggleSearch(display) {
    var sBox = $('#search');
    var lBox = lyricsDiv;
    if(typeof sBox == "undefined") {return;}
    sBox.toggle(display);
    var inverseBool=function(b){if(typeof b=="undefined"){return b}else{return !b}}
    lBox.toggle(inverseBool(display));
}

function setHeader(artist, title) {
    headerDiv.show(); //Make header visible
    var divArtist = $('#artist');
    divArtist.text(artist);
    var divTitle = $('#title');
    divTitle.text(title);
    autoSizeText(divArtist[0]); autoSizeText(divTitle[0]);
}

function checkIfNewSong(artist, title, callback) {
    if(!( (np.title == title) && (np.artist == artist) )) {
        callback(artist, title);
    }
}

function setCurrentTrack(artist, title) {
    lyricsDiv.hide();
    loaderDiv.show();
    NRdiv.hide();
    np.artist = artist; np.title = title;
    setHeader(artist, title);
    getLyrics(artist, title, function(succ, lyrics) {
        if(succ) {
            //Saving lyrics
            saveLyrics(artist, title, lyrics.toString());
            setLyrics(lyrics);
        }
        else {
            setLyrics('');
            lyricsDiv.hide();
            noLyricsDiv.show();
        }
    });
    window.scrollTo(0,0);
}

function setLyrics(lyrics) {
    lyricsDiv.show();
    lyricsDiv[0].innerText = lyrics; //jQuery would ignore the newlines
    noLyricsDiv.hide();
    loaderDiv.hide();
}

function cleanFileName(str, reverse) {
    var fakeSlash = String.fromCharCode(8725);
    var realSlash = "/";
    return str.replace(RegExp(reverse?fakeSlash:realSlash,"g"), reverse?realSlash:fakeSlash);
}

function saveLyrics(artist, title, lyrics) {
    if(!fs.existsSync(lyrics_dir)) {fs.mkdirSync(lyrics_dir)}
    artist = cleanFileName(artist.replace(/ /g, "_"));title = cleanFileName(title.replace(/ /g, "_"));
    fs.writeFile(lyrics_dir+'/'+artist+':'+title+'.txt', lyrics.toString()+'\n');
}

function readLyrics(artist, title, callback) {
    artist = cleanFileName(artist.replace(/ /g, "_"));title = cleanFileName(title.replace(/ /g, "_"));
    if(fs.existsSync(lyrics_dir+'/'+artist+':'+title+'.txt')) {
        fs.readFile(lyrics_dir+'/'+artist+':'+title+'.txt', 'utf8', function (error, data) {
            if(error) throw error
            if(callback == null) {
                setLyrics(data);
            }
            else { callback(true, data) }
        })
        return true;
    }
    else {return false}
}

function getLyrics(artist, title, callback) {
    if(!artist || !title) {return false}
    if(readLyrics(artist, title, callback)) {return;}
    var asyncLoop = function (arr, index) {
        var item = arr[index];
        if(item) {
            item.func(artist, title, function (succ, lyrics) {
                if(succ) {
                    callback(true, lyrics);
                }
                else {
                    asyncLoop(arr, index+1);
                }
            });
        }
        else {
            callback(false);
        }
    }
    asyncLoop(lyricsProviders, 0);
}

function addMenu() {
    var alignLyrics = function (pos) { lyricsDiv.css('text-align', pos); }
    var zoom = function (n) {if(n==0) {win.zoomLevel=0} else {win.zoomLevel = win.zoomLevel + n}}
    var menubar = new gui.Menu({type: 'menubar'});
    menubar.createMacBuiltin("Lyrics");
    var alignMenu = new gui.Menu(), zoomMenu = new gui.Menu();
    win.menu = menubar;
    var leftButton = new gui.MenuItem({ label: 'Left', click: function() { alignLyrics('left'); } });
    var centerButton = new gui.MenuItem({ label: 'Center', click: function() { alignLyrics('center'); } });
    var rightButton = new gui.MenuItem({ label: 'Right', click: function() { alignLyrics('right'); } });
    var zoomIn = new gui.MenuItem({ label: 'Zoom In', click: function() { zoom(1); } });
    var zoomOut = new gui.MenuItem({ label: 'Zoom out', click: function() { zoom(-1); } });
    var zoomReset = new gui.MenuItem({ label: 'Reset Zoom', click: function() { zoom(0); } });
    alignMenu.append(leftButton);
    alignMenu.append(centerButton);
    alignMenu.append(rightButton);
    zoomMenu.append(zoomIn);
    zoomMenu.append(zoomOut);
    zoomMenu.append(zoomReset);
    win.menu.insert(new gui.MenuItem({ label: 'Align', submenu: alignMenu }), 2)
    win.menu.insert(new gui.MenuItem({ label: 'Zoom', submenu: zoomMenu }), 3)
}

addMenu();
<commit_msg>Cmd+M -> Searches for current track on SongMeanings<commit_after>var itunes = require('playback');
var fs = require('fs');
var gui = require('nw.gui');
var win = gui.Window.get();
var app = gui.App;
var np = { };
var lyricsProviders = (function() {
    var obj = require('./lyricsProviders.js');
    var arr = new Array();
    $.each(obj, function(name, item) {
        arr.push(item);
    });
    return arr;
})();
var lyrics_dir = process.env['HOME']+'/.lyrics';
forceRefresh = false;

$(document).ready(function() {
   NRdiv = $('#iTunesNotRunning');
   lyricsDiv = $('#lyrics');
   headerDiv = $('#header');
   loaderDiv = $('#loader');
   noLyricsDiv = $('#NoLyricsFound');
   itunes.currentTrack();
});

win.on('close', function(event) {
    if(event=="quit") {
        win.close(true);
    }
    else{
        this.hide();
    }
});
app.on('reopen', function() {win.show(); win.focus()})
itunes.on('playing', function(data) {
   if(!data) {
        NRdiv.show();
        lyricsDiv.hide();
        headerDiv.hide();
        loaderDiv.hide();
        return;
   }
   if(forceRefresh) {setCurrentTrack(data.artist, data.title); forceRefresh=false;}
   checkIfNewSong(data.artist, data.name, function (artist, title) {
       setCurrentTrack(artist, title);
   });
})

win.on('enter-fullscreen', function() {$("html *").addClass('fullscreen'); lyricsDiv.hide(); setTimeout(function() {lyricsDiv.show();}, 0);});
win.on('leave-fullscreen', function() {$("html *").removeClass('fullscreen'); lyricsDiv.hide(); setTimeout(function() {lyricsDiv.show();}, 0);});
window.addEventListener('resize', function(event){
    autoSizeText($('#title')[0]);
    autoSizeText($('#artist')[0]);
});

$(document).keydown(function(evt) {
    if ((evt.which == '115' || evt.which == '83' ) && (evt.ctrlKey || evt.metaKey)) // Cmd+S
        {
            evt.preventDefault();
            lyricsDiv.removeClass('editmode');
            lyricsDiv.removeAttr('contenteditable');
            var lyrics = lyricsDiv[0].innerText;
            var artist = np.artist.replace(/ /g, "_"); var title = np.title.replace(/ /g, "_")
            saveLyrics(artist, title, lyrics);
            return false;
        }
    if ((evt.which == '109' || evt.which == '77' ) && (evt.ctrlKey || evt.metaKey)) // Cmd+M
        {
            evt.preventDefault();
            var artist = np.artist;
            var title = np.title;
            var query = artist + ' ' + title;
            gui.Shell.openExternal('http://songmeanings.com/query/?query='+encodeURIComponent(query));
            return false;
        }
    if (evt.keyCode == 27) { // Escape
            evt.preventDefault();
            lyricsDiv.removeClass('editmode');
            lyricsDiv.removeAttr('contenteditable');
            var artist = np.artist.replace(/ /g, "_"); var title = np.title.replace(/ /g, "_")
            toggleSearch(false);
            readLyrics(artist, title);
    }
    var tag = evt.target.tagName.toLowerCase();
    if (tag != 'input' && tag != 'textarea' && evt.target.getAttribute('contenteditable') != 'true') {
        if (String.fromCharCode(evt.keyCode) == "R") {
            forceRefresh = true;
            itunes.currentTrack();
        }
        if (String.fromCharCode(evt.keyCode) == "D") {
            require('nw.gui').Window.get().showDevTools()
        }
        if (String.fromCharCode(evt.keyCode) == "S") {
            toggleSearch();
        }
        if (String.fromCharCode(evt.keyCode) == "E") {
            editMode();
        }
    };
});

function autoSizeText(el) {
    el.style.fontSize = null;
    function resizeText() {
        var style = window.getComputedStyle(el);
        var elNewFontSize = (parseInt(style.getPropertyValue('font-size').slice(0,-2)) -1) + 'px';
        el.style.fontSize = elNewFontSize;
    }
    while (el.offsetWidth+50 > window.innerWidth) { resizeText(); }
}

function editMode(focus) {
    noLyricsDiv.hide();
    lyricsDiv.show();
    lyricsDiv.addClass("editmode");
    lyricsDiv.attr('contenteditable', "true");
    if(focus) { lyricsDiv.focus(); }
}

function markAsInstrumental(artist, title) {
    var artist = artist || np.artist;
    var title = title || np.title;
    saveLyrics(artist, title, "Instrumental");
    setLyrics('Instrumental');
    noLyricsDiv.hide();
    lyricsDiv.show();
}

function webSearch(artist, title) {
    var artist = artist || np.artist;
    var title = title || np.title;
    var query = artist + ' ' + title + ' lyrics';
    gui.Shell.openExternal('http://google.com/search?q='+encodeURIComponent(query));
}

function onSearch(e) {
    if (!e) e = window.event;
    if (e.keyCode == '13') {
        var aBox = $('#searchArtist');
        var tBox = $('#searchTitle');
        var artist = aBox.val();
        var title = tBox.val();
        toggleSearch();
        setCurrentTrack(artist, title);
    };
};

$('#searchArtist').keypress(onSearch);
$('#searchTitle').keypress(onSearch);

$('#header').dblclick(function() {
    var aBox = $('#searchArtist');
    var tBox = $('#searchTitle');
    aBox.val(np.artist);
    tBox.val(np.title);
    toggleSearch();
});

function toggleSearch(display) {
    var sBox = $('#search');
    var lBox = lyricsDiv;
    if(typeof sBox == "undefined") {return;}
    sBox.toggle(display);
    var inverseBool=function(b){if(typeof b=="undefined"){return b}else{return !b}}
    lBox.toggle(inverseBool(display));
}

function setHeader(artist, title) {
    headerDiv.show(); //Make header visible
    var divArtist = $('#artist');
    divArtist.text(artist);
    var divTitle = $('#title');
    divTitle.text(title);
    autoSizeText(divArtist[0]); autoSizeText(divTitle[0]);
}

function checkIfNewSong(artist, title, callback) {
    if(!( (np.title == title) && (np.artist == artist) )) {
        callback(artist, title);
    }
}

function setCurrentTrack(artist, title) {
    lyricsDiv.hide();
    loaderDiv.show();
    NRdiv.hide();
    np.artist = artist; np.title = title;
    setHeader(artist, title);
    getLyrics(artist, title, function(succ, lyrics) {
        if(succ) {
            //Saving lyrics
            saveLyrics(artist, title, lyrics.toString());
            setLyrics(lyrics);
        }
        else {
            setLyrics('');
            lyricsDiv.hide();
            noLyricsDiv.show();
        }
    });
    window.scrollTo(0,0);
}

function setLyrics(lyrics) {
    lyricsDiv.show();
    lyricsDiv[0].innerText = lyrics; //jQuery would ignore the newlines
    noLyricsDiv.hide();
    loaderDiv.hide();
}

function cleanFileName(str, reverse) {
    var fakeSlash = String.fromCharCode(8725);
    var realSlash = "/";
    return str.replace(RegExp(reverse?fakeSlash:realSlash,"g"), reverse?realSlash:fakeSlash);
}

function saveLyrics(artist, title, lyrics) {
    if(!fs.existsSync(lyrics_dir)) {fs.mkdirSync(lyrics_dir)}
    artist = cleanFileName(artist.replace(/ /g, "_"));title = cleanFileName(title.replace(/ /g, "_"));
    fs.writeFile(lyrics_dir+'/'+artist+':'+title+'.txt', lyrics.toString()+'\n');
}

function readLyrics(artist, title, callback) {
    artist = cleanFileName(artist.replace(/ /g, "_"));title = cleanFileName(title.replace(/ /g, "_"));
    if(fs.existsSync(lyrics_dir+'/'+artist+':'+title+'.txt')) {
        fs.readFile(lyrics_dir+'/'+artist+':'+title+'.txt', 'utf8', function (error, data) {
            if(error) throw error
            if(callback == null) {
                setLyrics(data);
            }
            else { callback(true, data) }
        })
        return true;
    }
    else {return false}
}

function getLyrics(artist, title, callback) {
    if(!artist || !title) {return false}
    if(readLyrics(artist, title, callback)) {return;}
    var asyncLoop = function (arr, index) {
        var item = arr[index];
        if(item) {
            item.func(artist, title, function (succ, lyrics) {
                if(succ) {
                    callback(true, lyrics);
                }
                else {
                    asyncLoop(arr, index+1);
                }
            });
        }
        else {
            callback(false);
        }
    }
    asyncLoop(lyricsProviders, 0);
}

function addMenu() {
    var alignLyrics = function (pos) { lyricsDiv.css('text-align', pos); }
    var zoom = function (n) {if(n==0) {win.zoomLevel=0} else {win.zoomLevel = win.zoomLevel + n}}
    var menubar = new gui.Menu({type: 'menubar'});
    menubar.createMacBuiltin("Lyrics");
    var alignMenu = new gui.Menu(), zoomMenu = new gui.Menu();
    win.menu = menubar;
    var leftButton = new gui.MenuItem({ label: 'Left', click: function() { alignLyrics('left'); } });
    var centerButton = new gui.MenuItem({ label: 'Center', click: function() { alignLyrics('center'); } });
    var rightButton = new gui.MenuItem({ label: 'Right', click: function() { alignLyrics('right'); } });
    var zoomIn = new gui.MenuItem({ label: 'Zoom In', click: function() { zoom(1); } });
    var zoomOut = new gui.MenuItem({ label: 'Zoom out', click: function() { zoom(-1); } });
    var zoomReset = new gui.MenuItem({ label: 'Reset Zoom', click: function() { zoom(0); } });
    alignMenu.append(leftButton);
    alignMenu.append(centerButton);
    alignMenu.append(rightButton);
    zoomMenu.append(zoomIn);
    zoomMenu.append(zoomOut);
    zoomMenu.append(zoomReset);
    win.menu.insert(new gui.MenuItem({ label: 'Align', submenu: alignMenu }), 2)
    win.menu.insert(new gui.MenuItem({ label: 'Zoom', submenu: zoomMenu }), 3)
}

addMenu();
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap
//= require_tree .

if ($('html').hasClass('himmeli')) {
  $('span[rel=tooltip]').tooltip({
    placement: "top"
  });
}

if (_.isNull(Himmeli)) Himmeli = {};
var controller = $('html').attr('class').split(' ').pop();

if (controller == 'people' && $('.person-details').length) {
  $.get('/people/' + Himmeli.id + '.json').then(function(data) {
    Himmeli['scoresPerEvent'] = data.scoresPerEvent;
    Himmeli['medianReplyTimes'] = data.medianReplyTimes;
    Himmeli['levelHighscores'] = data.levelHighscores;
  });

  $('.scores-chart-pills a').on('click', function(e) {
    e.preventDefault();

    var $tgt = $(e.target);
    $tgt.parent('li').addClass('active').siblings().removeClass('active');
    Himmeli.scoresPerEventChart($tgt.data('level'));
    Himmeli.medianReplyTimesChart($tgt.data('level'));
  });

  setTimeout(function() {
    Himmeli.scoresPerEventChart();
    Himmeli.medianReplyTimesChart();
  }, 500);
}

if (controller == 'game') {
  //
}

// Helper functions
Himmeli.scoresPerEventChart = function(level) {
  var lvl = level || 1,
    events = Himmeli.scoresPerEvent[lvl - 1],
    data = _.pluck(events, 'scores'),
    labels = [];

  _.each(events, function(e, index) {
    labels.push(e.aborted ? 'A' : index + 1);
  });

  var lineChartData = {
    labels: labels,
    datasets: [{
      fillColor: "rgba(151,187,205,0.5)",
      strokeColor: "rgba(151,187,205,1)",
      pointColor: "rgba(151,187,205,1)",
      pointStrokeColor: "#fff",
      data: data
    }]
  };

  var chartLine = new Chart(document.getElementById("scoresPerEventChart").getContext("2d")).Bar(lineChartData);
};

Himmeli.medianReplyTimesChart = function(level) {
  var lvl = level || 1,
    data = Himmeli.medianReplyTimes[lvl - 1],
    labels = [];

  _.each(data, function(e, index) {
    labels.push(index + 1);
  });

  var lineChartData = {
    labels: labels,
    datasets: [{
      fillColor: "rgba(151,187,205,0.5)",
      strokeColor: "rgba(151,187,205,1)",
      pointColor: "rgba(151,187,205,1)",
      pointStrokeColor: "#fff",
      data: data
    }]
  };

  var chartLine = new Chart(document.getElementById("medianReplyTimesChart").getContext("2d")).Line(lineChartData);
};

Himmeli.addEvent = function(gameEvent) {
  // token
  var token = $('input[name=authenticity_token]').val();

  // request object
  var json = {
    'utf8': '✓',
    'authenticity_token': token,
    'event': gameEvent
  };

  // request
  return $.ajax({
    dataType: 'json',
    method: 'post',
    url: '/events',
    data: json
  });
};

Himmeli.updatePersonLevel = function(level) {
  // token
  var token = $('input[name=authenticity_token]').val();

  // request object
  var json = {
    'utf8': '✓',
    'authenticity_token': token,
    'person': {
      'level': level
    }
  };

  // request
  return $.ajax({
    dataType: 'json',
    method: 'put',
    url: '/people/' + Himmeli.id,
    data: json
  });
};

Himmeli.getVersions = function() {
  return $.getJSON('/versions.json');
};

Himmeli.statsView = function() {
  var $body = $('body');

  var stats = '

' +
    'Palaa peliin' +
    '
Pelaajan kehittyminen
' +
    '
Nimi: ' + Himmeli.first_name + ' ' + Himmeli.last_name + '
' +
    '
' +
    '
' +
    '
Taso 1
' +
    '
Taso 2
' +
    '
Taso 3
' +
    '
Taso 4
' +
    '
Taso 5
' +
    '
Taso 6
' +
    '
' +
    '
' +
    '
Pisteitä per pelikerta
' +
    '<canvas id="scoresPerEventChart" width="738" height="400"></canvas>' +
    '
Keskimääräinen vastausaika (mediaani)
' +
    '<canvas id="medianReplyTimesChart" width="738" height="400"></canvas>' +
    '

';

  $body.append(stats);

  $('.scores-chart-pills a').on('click', function(e) {
    e.preventDefault();

    var $tgt = $(e.target);
    $tgt.parent('li').addClass('active').siblings().removeClass('active');
    Himmeli.scoresPerEventChart($tgt.data('level'));
    Himmeli.medianReplyTimesChart($tgt.data('level'));
  });

  $('.close-btn').on('click', function(e) {
    e.preventDefault();

    $('.stats').fadeOut(700, function() {
      $('.close-btn').off('click');
      $('.scores-chart-pills a').off('click');
      $('.stats').remove();
    });
  });

  // update stats
  $.get('/people/' + Himmeli.id + '.json').then(function(data) {
    Himmeli['scoresPerEvent'] = data.scoresPerEvent;
    Himmeli['medianReplyTimes'] = data.medianReplyTimes;

    $('.stats').fadeIn(700, function() {
      setTimeout(function() {
        Himmeli.scoresPerEventChart();
        Himmeli.medianReplyTimesChart();
      }, 500);
    });
  });
};

$('body').on('click', '.help_button', function(e) {
  Himmeli.statsView();
});

/*
var gameEvent = {
  'person_id': 2,
  'version_id': 1,
  'duration': 1098,
  'level': 4,
  'scores': 3,
  'aborted': 1,
  'items_attributes': [{
    'duration': 23939,
    'answer': 1,
    'pointer': 1,
    'target': 1
  }, {
    'duration': 23939,
    'answer': 1,
    'pointer': 1,
    'target': 1
  },{
    'duration': 23939,
    'answer': 1,
    'pointer': 1,
    'target': 1
  }, {
    'duration': 23939,
    'answer': 1,
    'pointer': 1,
    'target': 1
  }]
};
console.log(Himmeli.addEvent(gameEvent));
*/<commit_msg>cr-stage<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap
//= require_tree .

if ($('html').hasClass('himmeli')) {
  $('span[rel=tooltip]').tooltip({
    placement: "top"
  });
}

if (_.isNull(Himmeli)) Himmeli = {};
var controller = $('html').attr('class').split(' ').pop();

if (controller == 'people' && $('.person-details').length) {
  $.get('/people/' + Himmeli.id + '.json').then(function(data) {
    Himmeli['scoresPerEvent'] = data.scoresPerEvent;
    Himmeli['medianReplyTimes'] = data.medianReplyTimes;
    Himmeli['levelHighscores'] = data.levelHighscores;
  });

  $('.scores-chart-pills a').on('click', function(e) {
    e.preventDefault();

    var $tgt = $(e.target);
    $tgt.parent('li').addClass('active').siblings().removeClass('active');
    Himmeli.scoresPerEventChart($tgt.data('level'));
    Himmeli.medianReplyTimesChart($tgt.data('level'));
  });

  setTimeout(function() {
    Himmeli.scoresPerEventChart();
    Himmeli.medianReplyTimesChart();
  }, 500);
}

if (controller == 'game') {
  //
}

// Helper functions
Himmeli.scoresPerEventChart = function(level) {
  var lvl = level || 1,
    events = Himmeli.scoresPerEvent[lvl - 1],
    data = _.pluck(events, 'scores'),
    labels = [];

  _.each(events, function(e, index) {
    labels.push(e.aborted ? 'A' : index + 1);
  });

  var lineChartData = {
    labels: labels,
    datasets: [{
      fillColor: "rgba(151,187,205,0.5)",
      strokeColor: "rgba(151,187,205,1)",
      pointColor: "rgba(151,187,205,1)",
      pointStrokeColor: "#fff",
      data: data
    }]
  };

  var chartLine = new Chart(document.getElementById("scoresPerEventChart").getContext("2d")).Bar(lineChartData);
};

Himmeli.medianReplyTimesChart = function(level) {
  var lvl = level || 1,
    data = Himmeli.medianReplyTimes[lvl - 1],
    labels = [];

  _.each(data, function(e, index) {
    labels.push(index + 1);
  });

  var lineChartData = {
    labels: labels,
    datasets: [{
      fillColor: "rgba(151,187,205,0.5)",
      strokeColor: "rgba(151,187,205,1)",
      pointColor: "rgba(151,187,205,1)",
      pointStrokeColor: "#fff",
      data: data
    }]
  };

  var chartLine = new Chart(document.getElementById("medianReplyTimesChart").getContext("2d")).Line(lineChartData);
};

Himmeli.addEvent = function(gameEvent) {
  // token
  var token = $('input[name=authenticity_token]').val();

  // request object
  var json = {
    'utf8': '✓',
    'authenticity_token': token,
    'event': gameEvent
  };

  // request
  return $.ajax({
    dataType: 'json',
    method: 'post',
    url: '/events',
    data: json
  });
};

Himmeli.updatePersonLevel = function(level) {
  // token
  var token = $('input[name=authenticity_token]').val();

  // request object
  var json = {
    'utf8': '✓',
    'authenticity_token': token,
    'person': {
      'level': level
    }
  };

  // request
  return $.ajax({
    dataType: 'json',
    method: 'put',
    url: '/people/' + Himmeli.id,
    data: json
  });
};

Himmeli.getVersions = function() {
  return $.getJSON('/versions.json');
};

Himmeli.statsView = function() {
  var $body = $('body');

  var stats = '

' +
    'Palaa peliin' +
    '
Pelaajan kehittyminen
' +
    '
Nimi: ' + Himmeli.first_name + ' ' + Himmeli.last_name + '
' +
    '
' +
    '
' +
    '
Taso 1
' +
    '
Taso 2
' +
    '
Taso 3
' +
    '
Taso 4
' +
    '
Taso 5
' +
    '
Taso 6
' +
    '
' +
    '
' +
    '
Pisteitä per pelikerta
' +
    '<canvas id="scoresPerEventChart" width="738" height="400"></canvas>' +
    '
Keskimääräinen vastausaika (mediaani)
' +
    '<canvas id="medianReplyTimesChart" width="738" height="400"></canvas>' +
    '

';

  $body.append(stats);

  $('.scores-chart-pills a').on('click', function(e) {
    e.preventDefault();

    var $tgt = $(e.target);
    $tgt.parent('li').addClass('active').siblings().removeClass('active');
    Himmeli.scoresPerEventChart($tgt.data('level'));
    Himmeli.medianReplyTimesChart($tgt.data('level'));
  });

  $('.close-btn').on('click', function(e) {
    e.preventDefault();

    $('.stats').fadeOut(700, function() {
      $('.close-btn').off('click');
      $('.scores-chart-pills a').off('click');
      $('.stats').remove();
      $('#cr-stage').show();
    });
  });

  // update stats
  $.get('/people/' + Himmeli.id + '.json').then(function(data) {
    Himmeli['scoresPerEvent'] = data.scoresPerEvent;
    Himmeli['medianReplyTimes'] = data.medianReplyTimes;

    $('.stats').fadeIn(700, function() {
      setTimeout(function() {
        Himmeli.scoresPerEventChart();
        Himmeli.medianReplyTimesChart();
      }, 500);
    });
  });
};

$('body').on('click', '.help_button', function(e) {
  Himmeli.statsView();
  $('#cr-stage').hide();
});

/*
var gameEvent = {
  'person_id': 2,
  'version_id': 1,
  'duration': 1098,
  'level': 4,
  'scores': 3,
  'aborted': 1,
  'items_attributes': [{
    'duration': 23939,
    'answer': 1,
    'pointer': 1,
    'target': 1
  }, {
    'duration': 23939,
    'answer': 1,
    'pointer': 1,
    'target': 1
  },{
    'duration': 23939,
    'answer': 1,
    'pointer': 1,
    'target': 1
  }, {
    'duration': 23939,
    'answer': 1,
    'pointer': 1,
    'target': 1
  }]
};
console.log(Himmeli.addEvent(gameEvent));
*/<|endoftext|>


<commit_before>const consumeMessages = require('./messages/consumeMessages')
const app = require('kth-node-server')
const systemRoutes = require('./server/systemroutes')
const config = require('./config')
const log = require('./server/logging')

consumeMessages.onDetached = function (msg) {
  log.info('On detached: restart process')
  process.send({action: 'restart'})
}

// This is a temporary fix to make sure that the ref server won't run with the
// production settings. It can safely be removed once we only use docker.
if (config.dontRun) {
  log.info('dontRun is set, skip consuming messages')
} else {
  consumeMessages.start()
}

app.use(config.proxyPrefixPath.uri, systemRoutes)
app.start()
<commit_msg>use logger for express app<commit_after>const consumeMessages = require('./messages/consumeMessages')
const app = require('kth-node-server')
const systemRoutes = require('./server/systemroutes')
const config = require('./config')
const log = require('./server/logging')

consumeMessages.onDetached = function (msg) {
  log.info('On detached: restart process')
  process.send({action: 'restart'})
}

// This is a temporary fix to make sure that the ref server won't run with the
// production settings. It can safely be removed once we only use docker.
if (config.dontRun) {
  log.info('dontRun is set, skip consuming messages')
} else {
  consumeMessages.start()
}

app.use(config.proxyPrefixPath.uri, systemRoutes)
app.start({logger:log})
<|endoftext|>


<commit_before>'use strict';

/* global -$ */

var $ = document.querySelector.bind(document);

var renderPng = function(canvasSelector, imgSelector) {
  var imgSrc = $(canvasSelector).toDataURL('image/png');
  $(imgSelector).setAttribute('src', imgSrc);
};

//////////////////////////////
// Colors

var BLACK = '#000';
var WHITE = '#fff';
var GRAY = '#777';
var PURPLE = '#66c';
var DARK_PURPLE = '#448';

//////////////////////////////
// Logo

var drawOneLogo = function(canvasSelector, spanSelector, font) {
  var canvas = $(canvasSelector);
  canvas.width = $(spanSelector).offsetWidth;
  canvas.height = $(spanSelector).offsetHeight;

  var ctx = canvas.getContext('2d');

  ctx.fillStyle = DARK_PURPLE;
  ctx.fillRect(0, 0, 1000, 1000);
  ctx.fill();

  ctx.font = font;
  ctx.fillStyle = WHITE;
  ctx.textAlign = 'left';
  ctx.textBaseline = 'alphabetic';
  ctx.fillText('tadue', 0, canvas.height - 1);
};

var drawLogos = function() {
  drawOneLogo('#logo', '#css_logo', '60px Alice');
  renderPng('#logo', '#ilogo');

  drawOneLogo('#logo_small', '#css_logo_small', '40px Alice');
  renderPng('#logo_small', '#ilogo_small');
};

// Add a delay to allow font to load.
setTimeout(drawLogos, 200);

//////////////////////////////
// Icons

var RADIUS = 10;
var DIAMETER = 2 * RADIUS;
var LINE_LENGTH = 12;

var initCanvas = function(canvasSelector, width, height) {
  var canvas = $(canvasSelector);
  canvas.width = width;
  canvas.height = height;
  return canvas.getContext('2d');
};

var drawLine = function(ctx, startX, color, vertical) {
  ctx.strokeStyle = color;
  ctx.lineWidth = 2;
  ctx.beginPath();
  if (vertical) {
    ctx.moveTo(startX + RADIUS, RADIUS - LINE_LENGTH / 2);
    ctx.lineTo(startX + RADIUS, RADIUS + LINE_LENGTH / 2);
  } else {
    ctx.moveTo(startX + RADIUS - LINE_LENGTH / 2, RADIUS);
    ctx.lineTo(startX + RADIUS + LINE_LENGTH / 2, RADIUS);
  }
  ctx.stroke();
};

var drawMinus = function(ctx, startX, color) {
  drawLine(ctx, startX, color, false);
};

var drawPlus = function(ctx, startX, color) {
  drawLine(ctx, startX, color, false);
  drawLine(ctx, startX, color, true);
};

var X_WIDTH = 9;
var X_LINE_WIDTH = 2;

var drawX = function(ctx) {
  ctx.strokeStyle = GRAY;
  ctx.lineWidth = X_LINE_WIDTH;
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.lineTo(X_WIDTH, X_WIDTH);
  ctx.moveTo(0, X_WIDTH);
  ctx.lineTo(X_WIDTH, 0);
  ctx.stroke();
};

var FAVICON_WIDTH = 16;

var drawFavicon = function(ctx) {
  // Fill the background.
  ctx.fillStyle = DARK_PURPLE;
  ctx.fillRect(0, 0, FAVICON_WIDTH, FAVICON_WIDTH);
  // Draw the "t".
  // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors#A_lineWidth_example
  ctx.strokeStyle = WHITE;
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(3.5, 6);
  ctx.lineTo(3.5, 13);
  ctx.moveTo(2, 8.5);
  ctx.lineTo(6, 8.5);
  ctx.moveTo(4, 13.5);
  ctx.lineTo(6, 13.5);
  ctx.moveTo(6, 12.5);
  ctx.lineTo(7, 12.5);
  ctx.stroke();
};

var drawIcons = function() {
  var ctx = initCanvas('#plus', DIAMETER, DIAMETER);
  drawPlus(ctx, 0, PURPLE);
  renderPng('#plus', '#iplus');

  ctx = initCanvas('#plus-active', DIAMETER, DIAMETER);
  drawPlus(ctx, 0, BLACK);
  renderPng('#plus-active', '#iplus-active');

  ctx = initCanvas('#minus', DIAMETER, DIAMETER);
  drawMinus(ctx, 0, PURPLE);
  renderPng('#minus', '#iminus');

  ctx = initCanvas('#minus-active', DIAMETER, DIAMETER);
  drawMinus(ctx, 0, BLACK);
  renderPng('#minus-active', '#iminus-active');

  ctx = initCanvas('#close', X_WIDTH, X_WIDTH);
  drawX(ctx);
  renderPng('#close', '#iclose');

  ctx = initCanvas('#favicon', FAVICON_WIDTH, FAVICON_WIDTH);
  drawFavicon(ctx);
  renderPng('#favicon', '#ifavicon');  // png and ico have the same format
};

drawIcons();
<commit_msg>s/drawIcons/makeImages/<commit_after>'use strict';

/* global -$ */

var $ = document.querySelector.bind(document);

var renderPng = function(canvasSelector, imgSelector) {
  var imgSrc = $(canvasSelector).toDataURL('image/png');
  $(imgSelector).setAttribute('src', imgSrc);
};

//////////////////////////////
// Colors

var BLACK = '#000';
var WHITE = '#fff';
var GRAY = '#777';
var PURPLE = '#66c';
var DARK_PURPLE = '#448';

//////////////////////////////
// Logo

var drawOneLogo = function(canvasSelector, spanSelector, font) {
  var canvas = $(canvasSelector);
  canvas.width = $(spanSelector).offsetWidth;
  canvas.height = $(spanSelector).offsetHeight;

  var ctx = canvas.getContext('2d');

  ctx.fillStyle = DARK_PURPLE;
  ctx.fillRect(0, 0, 1000, 1000);
  ctx.fill();

  ctx.font = font;
  ctx.fillStyle = WHITE;
  ctx.textAlign = 'left';
  ctx.textBaseline = 'alphabetic';
  ctx.fillText('tadue', 0, canvas.height - 1);
};

var drawLogos = function() {
  drawOneLogo('#logo', '#css_logo', '60px Alice');
  renderPng('#logo', '#ilogo');

  drawOneLogo('#logo_small', '#css_logo_small', '40px Alice');
  renderPng('#logo_small', '#ilogo_small');
};

// Add a delay to allow font to load.
setTimeout(drawLogos, 200);

//////////////////////////////
// Icons

var RADIUS = 10;
var DIAMETER = 2 * RADIUS;
var LINE_LENGTH = 12;

var initCanvas = function(canvasSelector, width, height) {
  var canvas = $(canvasSelector);
  canvas.width = width;
  canvas.height = height;
  return canvas.getContext('2d');
};

var drawLine = function(ctx, startX, color, vertical) {
  ctx.strokeStyle = color;
  ctx.lineWidth = 2;
  ctx.beginPath();
  if (vertical) {
    ctx.moveTo(startX + RADIUS, RADIUS - LINE_LENGTH / 2);
    ctx.lineTo(startX + RADIUS, RADIUS + LINE_LENGTH / 2);
  } else {
    ctx.moveTo(startX + RADIUS - LINE_LENGTH / 2, RADIUS);
    ctx.lineTo(startX + RADIUS + LINE_LENGTH / 2, RADIUS);
  }
  ctx.stroke();
};

var drawMinus = function(ctx, startX, color) {
  drawLine(ctx, startX, color, false);
};

var drawPlus = function(ctx, startX, color) {
  drawLine(ctx, startX, color, false);
  drawLine(ctx, startX, color, true);
};

var X_WIDTH = 9;
var X_LINE_WIDTH = 2;

var drawX = function(ctx) {
  ctx.strokeStyle = GRAY;
  ctx.lineWidth = X_LINE_WIDTH;
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.lineTo(X_WIDTH, X_WIDTH);
  ctx.moveTo(0, X_WIDTH);
  ctx.lineTo(X_WIDTH, 0);
  ctx.stroke();
};

var FAVICON_WIDTH = 16;

var drawFavicon = function(ctx) {
  // Fill the background.
  ctx.fillStyle = DARK_PURPLE;
  ctx.fillRect(0, 0, FAVICON_WIDTH, FAVICON_WIDTH);
  // Draw the "t".
  // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors#A_lineWidth_example
  ctx.strokeStyle = WHITE;
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(3.5, 6);
  ctx.lineTo(3.5, 13);
  ctx.moveTo(2, 8.5);
  ctx.lineTo(6, 8.5);
  ctx.moveTo(4, 13.5);
  ctx.lineTo(6, 13.5);
  ctx.moveTo(6, 12.5);
  ctx.lineTo(7, 12.5);
  ctx.stroke();
};

var makeImages = function() {
  var ctx = initCanvas('#plus', DIAMETER, DIAMETER);
  drawPlus(ctx, 0, PURPLE);
  renderPng('#plus', '#iplus');

  ctx = initCanvas('#plus-active', DIAMETER, DIAMETER);
  drawPlus(ctx, 0, BLACK);
  renderPng('#plus-active', '#iplus-active');

  ctx = initCanvas('#minus', DIAMETER, DIAMETER);
  drawMinus(ctx, 0, PURPLE);
  renderPng('#minus', '#iminus');

  ctx = initCanvas('#minus-active', DIAMETER, DIAMETER);
  drawMinus(ctx, 0, BLACK);
  renderPng('#minus-active', '#iminus-active');

  ctx = initCanvas('#close', X_WIDTH, X_WIDTH);
  drawX(ctx);
  renderPng('#close', '#iclose');

  ctx = initCanvas('#favicon', FAVICON_WIDTH, FAVICON_WIDTH);
  drawFavicon(ctx);
  renderPng('#favicon', '#ifavicon');  // png and ico have the same format
};

makeImages();
<|endoftext|>


<commit_before>/**
 * @file LandingFoot.js
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React from 'react';

// Components
import IconAnchor from 'src/IconAnchor';

// Styles
import 'scss/containers/landing/LandingFoot.scss';

function LandingFoot() {
    return (

                Alcedo-UI
                 is freely distributable under the terms of the

                    {' MIT license'}
                .

            <IconAnchor className="github-icon"
                        iconCls="fab fa-github"
                        href="https://github.com/alcedo-ui/alcedo-ui"/>

    );
}

export default LandingFoot;
<commit_msg>update LandingFoot<commit_after>/**
 * @file LandingFoot.js
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React from 'react';

// Components
import IconAnchor from 'src/IconAnchor';

// Styles
import 'scss/containers/landing/LandingFoot.scss';

function LandingFoot() {
    return (

            <>
                Alcedo-UI
                 is freely distributable under the terms of the

                    {' MIT license'}
                .
            </>

            <IconAnchor className="github-icon"
                        iconCls="fab fa-github"
                        href="https://github.com/alcedo-ui/alcedo-ui"/>

    );
}

export default LandingFoot;
<|endoftext|>


<commit_before>/*jslint browser: true*/
/*global define*/

//-----------------------------------------------------------------------

define(['data/berlin', 'data/brandenburg', 'data/moers', 'data/wesel'], function (dataBerlin, dataBrandenburg, dataMoers, dataWesel) {
	'use strict';

	var firstDay = 4000000000000,
		lastDay = 0,
		market,
		markets = [];

	function addData(name, data) {
		for (market = 0; market < data.length; ++market) {
			data[market].path = name.toLowerCase();
			if (!isNaN(Date.parse(data[market].begin))) {
				firstDay = Math.min(firstDay, Date.parse(data[market].begin));
			}
			if (!isNaN(Date.parse(data[market].end))) {
				lastDay = Math.max(lastDay, Date.parse(data[market].end));
			}
		}

		markets = markets.concat(data);
	}

//	addData('Berlin', dataBerlin.data);
//	addData('Brandenburg', dataBrandenburg.data);
//	addData('Moers', dataMoers.data);
	addData('Wesel', dataWesel.data);

	return {
		timeout: 400,
		currentMarketId: 0,
		startDate: new Date(firstDay),
		endDate: new Date(lastDay + (1000 * 60 * 60 * 24)),
		views: [],
		markets: markets,
		userLat: null,
		userLon: null,

		getMarketByID: function (marketId) {
			var path = marketId.split('-')[0],
				uuid = parseInt(marketId.split('-')[1], 10),
				i;

			for (i = 0; i < this.markets.length; ++i) {
				if ((this.markets[i].path === path) && (this.markets[i].uuid === uuid)) {
					return this.markets[i];
				}
			}

			return null;
		}
	};
});

//-----------------------------------------------------------------------
<commit_msg>no message<commit_after>/*jslint browser: true*/
/*global define*/

//-----------------------------------------------------------------------

//define(['data/berlin', 'data/brandenburg', 'data/moers', 'data/wesel'], function (dataBerlin, dataBrandenburg, dataMoers, dataWesel) {
define(['data/berlin', 'data/brandenburg', 'data/moers'], function (dataBerlin, dataBrandenburg, dataMoers) {
	'use strict';

	var firstDay = 4000000000000,
		lastDay = 0,
		market,
		markets = [];

	function addData(name, data) {
		for (market = 0; market < data.length; ++market) {
			data[market].path = name.toLowerCase();
			if (!isNaN(Date.parse(data[market].begin))) {
				firstDay = Math.min(firstDay, Date.parse(data[market].begin));
			}
			if (!isNaN(Date.parse(data[market].end))) {
				lastDay = Math.max(lastDay, Date.parse(data[market].end));
			}
		}

		markets = markets.concat(data);
	}

//	addData('Berlin', dataBerlin.data);
//	addData('Brandenburg', dataBrandenburg.data);
	addData('Moers', dataMoers.data);
//	addData('Wesel', dataWesel.data);

	return {
		timeout: 400,
		currentMarketId: 0,
		startDate: new Date(firstDay),
		endDate: new Date(lastDay + (1000 * 60 * 60 * 24)),
		views: [],
		markets: markets,
		userLat: null,
		userLon: null,

		getMarketByID: function (marketId) {
			var path = marketId.split('-')[0],
				uuid = parseInt(marketId.split('-')[1], 10),
				i;

			for (i = 0; i < this.markets.length; ++i) {
				if ((this.markets[i].path === path) && (this.markets[i].uuid === uuid)) {
					return this.markets[i];
				}
			}

			return null;
		}
	};
});

//-----------------------------------------------------------------------
<|endoftext|>


<commit_before>var fs = require('fs'),
  prettyjson = require('./prettyjson'),
  cases = require('./cases'),
  found = false;
fs.readdir('points/', function(err, files) {
  if(err) {
    console.log(err, 'readdir');
    process.exit(1);
  } else {
    for(var i=0; i<files.length; i++) {
      if(files[i] != 'README.md') {
        doFile(files[i]);
      }
    }
  }
});
function doFile(fileName) {
  fs.readFile('points/'+fileName, function(err, data) {
    try {
      if(err) {
        console.log(err, fileName);
        process.exit(1);
      } else {
        var obj, changed = false;
        try {
          obj = JSON.parse(data);
        } catch(e) {
          console.log(e, fileName);
          process.exit(1);
        }
        if(obj.tosdr.disputed || obj.tosdr.irrelevant || !obj.tosdr.binding || typeof(obj.tosdr)=='undefined'
                        || typeof(obj.tosdr.point)=='undefined' || typeof(obj.tosdr.score)=='undefined'
                        || typeof(obj.tosdr.tldr)=='undefined' ) {
          return;
        }
        if(found || !cases[obj.topics[0]] || obj.tosdr.case) {
          return;
        }
        var topic = obj.topics[0];
        found = true;
        console.log(obj, '\nplease assign a case:\n', cases[obj.topics[0]]);
        var stdin = process.openStdin();
        stdin.on('data', function(chunk) {
          chunk = chunk.toString();
          chunk = chunk.substring(0, chunk.length-1);
          console.log("Got chunk: " + chunk);
          console.log(typeof(chunk), chunk.length, cases[topic]);
          obj.tosdr.case = cases[topic][chunk].name;
          obj.tosdr.point = cases[topic][chunk].point;
          obj.tosdr.score = cases[topic][chunk].score;
          fs.writeFileSync('points/'+fileName, prettyjson(obj));
          process.exit();
        });
        console.log('please choose a case!');
      }
    } catch(e) {
      console.log(e, fileName);
      process.exit(1);
    }
    //console.log('async end ', fileName);
  });
  console.log('sync end ', fileName);
}
<commit_msg>less verbose checkcases.js<commit_after>var fs = require('fs'),
  prettyjson = require('./prettyjson'),
  cases = require('./cases'),
  found = false;
fs.readdir('points/', function(err, files) {
  if(err) {
    console.log(err, 'readdir');
    process.exit(1);
  } else {
    for(var i=0; i<files.length; i++) {
      if(files[i] != 'README.md') {
        doFile(files[i]);
      }
    }
  }
});
function doFile(fileName) {
  fs.readFile('points/'+fileName, function(err, data) {
    try {
      if(err) {
        console.log(err, fileName);
        process.exit(1);
      } else {
        var obj, changed = false;
        try {
          obj = JSON.parse(data);
        } catch(e) {
          console.log(e, fileName);
          process.exit(1);
        }
        if(obj.tosdr.disputed || obj.tosdr.irrelevant || !obj.tosdr.binding || typeof(obj.tosdr)=='undefined'
                        || typeof(obj.tosdr.point)=='undefined' || typeof(obj.tosdr.score)=='undefined'
                        || typeof(obj.tosdr.tldr)=='undefined' ) {
          return;
        }
        if(found || !cases[obj.topics[0]] || obj.tosdr.case) {
          return;
        }
        var topic = obj.topics[0];
        found = true;
        console.log(obj, '\nplease assign a case:\n', cases[obj.topics[0]]);
        var stdin = process.openStdin();
        stdin.on('data', function(chunk) {
          chunk = chunk.toString();
          chunk = chunk.substring(0, chunk.length-1);
          console.log("Got chunk: " + chunk);
          console.log(typeof(chunk), chunk.length, cases[topic]);
          obj.tosdr.case = cases[topic][chunk].name;
          obj.tosdr.point = cases[topic][chunk].point;
          obj.tosdr.score = cases[topic][chunk].score;
          fs.writeFileSync('points/'+fileName, prettyjson(obj));
          process.exit();
        });
        console.log('please choose a case!');
      }
    } catch(e) {
      console.log(e, fileName);
      process.exit(1);
    }
  });
}
<|endoftext|>


<commit_before>var Monad = require('./monad');

function run(tasks, value) {
	while (tasks.length) setTimeout(tasks.shift(), 0, value);
}

function pendingValue(producer) {
	var isPending = true, value, pending = [];

	producer(function(result) {
		isPending = false;
		value = result;

		run(pending, value);
	});

	return function(next) {
		if (isPending) {
			pending.push(next);
		} else {
			run([next], value);
		}
	};
}

function flatten(value, resolve) {
	if (Monad.isMonad(value)) {
		value.bind(resolve);
	} else {
		resolve(value);
	}
}

function Future(producer) {
	var wrappedProducer = pendingValue(producer);

	return {
		isMonad: true,
		bind: function(right) {
			return Future(function(resolve) {
				wrappedProducer(function(value) {
					flatten(right(value), resolve);
				});
			});
		}
	};
}

// exports.Resolve = Resolve;
// exports.Reject = Reject;
exports.Future = Future;
<commit_msg>reject part<commit_after>var Monad = require('./monad');

function run(tasks, value) {
	while (tasks.length) setTimeout(tasks.shift(), 0, value);
}

function pendingValue(producer) {
	var isPending = true, value, pending = [];

	producer(function(result) {
		isPending = false;
		value = result;

		run(pending, value);
	}, function(error) {
		// TODO: implement left part
	});

	return function(next) {
		if (isPending) {
			pending.push(next);
		} else {
			run([next], value);
		}
	};
}

function flatten(value, right, left) {
	if (Monad.isMonad(value)) {
		return value.bind(right, left);
	} else {
		return right(value);
	}
}

function Future(producer) {
	var wrappedProducer = pendingValue(producer);

	return {
		isMonad: true,
		bind: function(right) {
			return Future(function(resolve, reject) {
				wrappedProducer(function(value) {
					flatten(right(value), resolve, reject);
				});
			});
		}
	};
}

// exports.Resolve = Resolve;
// exports.Reject = Reject;
exports.Future = Future;
<|endoftext|>


<commit_before>/*
GreedyNav.js - http://lukejacksonn.com/actuate
Licensed under the MIT license - http://opensource.org/licenses/MIT
Copyright (c) 2015 Luke Jackson
*/

$(function() {

  var $nav = $('nav.greedy');
  var $btn = $('nav.greedy button');
  var $vlinks = $('nav.greedy .links');
  var $hlinks = $('nav.greedy .hidden-links');

  var numOfItems = 0;
  var totalSpace = 0;
  var breakWidths = [];

  // Get initial state
  $vlinks.children().outerWidth(function(i, w) {
    totalSpace += w;
    numOfItems += 1;
    breakWidths.push(totalSpace);
  });

  var availableSpace, numOfVisibleItems, requiredSpace;

  function check() {

    // Get instant state
    availableSpace = $vlinks.width() - 10;
    numOfVisibleItems = $vlinks.children().length;
    requiredSpace = breakWidths[numOfVisibleItems - 1];

    // There is not enought space
    if (requiredSpace > availableSpace) {
      $vlinks.children().last().prependTo($hlinks);
      numOfVisibleItems -= 1;
      check();
      // There is more than enough space
    } else if (availableSpace > breakWidths[numOfVisibleItems]) {
      $hlinks.children().first().appendTo($vlinks);
      numOfVisibleItems += 1;
    }
    // Update the button accordingly
    $btn.attr("count", numOfItems - numOfVisibleItems);
    if (numOfVisibleItems === numOfItems) {
      $btn.addClass('hidden');
    } else $btn.removeClass('hidden');
  }

  // Window listeners
  $(window).resize(function() {
    check();
  });

  $btn.on('click', function() {
    $hlinks.toggleClass('hidden');
  });

  check();

});
<commit_msg>Updated greedynav.js - deleted unused var<commit_after>/*
GreedyNav.js - http://lukejacksonn.com/actuate
Licensed under the MIT license - http://opensource.org/licenses/MIT
Copyright (c) 2015 Luke Jackson
*/

$(function() {

  var $btn = $('nav.greedy button');
  var $vlinks = $('nav.greedy .links');
  var $hlinks = $('nav.greedy .hidden-links');

  var numOfItems = 0;
  var totalSpace = 0;
  var breakWidths = [];

  // Get initial state
  $vlinks.children().outerWidth(function(i, w) {
    totalSpace += w;
    numOfItems += 1;
    breakWidths.push(totalSpace);
  });

  var availableSpace, numOfVisibleItems, requiredSpace;

  function check() {

    // Get instant state
    availableSpace = $vlinks.width() - 10;
    numOfVisibleItems = $vlinks.children().length;
    requiredSpace = breakWidths[numOfVisibleItems - 1];

    // There is not enought space
    if (requiredSpace > availableSpace) {
      $vlinks.children().last().prependTo($hlinks);
      numOfVisibleItems -= 1;
      check();
      // There is more than enough space
    } else if (availableSpace > breakWidths[numOfVisibleItems]) {
      $hlinks.children().first().appendTo($vlinks);
      numOfVisibleItems += 1;
    }
    // Update the button accordingly
    $btn.attr("count", numOfItems - numOfVisibleItems);
    if (numOfVisibleItems === numOfItems) {
      $btn.addClass('hidden');
    } else $btn.removeClass('hidden');
  }

  // Window listeners
  $(window).resize(function() {
    check();
  });

  $btn.on('click', function() {
    $hlinks.toggleClass('hidden');
  });

  check();

});
<|endoftext|>


<commit_before>module.exports = function(grunt) {

    var gruntConfig = {

        "clean": {
            "content": ['dist/*', 'public/*']
        },

        "pkg": grunt.file.readJSON('package.json'),
        "uglify": {
            "options": {
                "banner": '/*! <%= pkg.name %> <%= pkg.version %> <%= grunt.template.today("yyyy-mm-dd") %> */',
                "wrap": true,
                "sourceMap": true,
                "sourceMapIncludeSources": true,
                "sourceMapName": 'dist/<%= pkg.name %>.min.js.map'
            },
            "build": {
                "src": [
                    'src/jquery-ajax.js',
                    'src/*.js'

                ],
                "dest": 'dist/<%= pkg.name %>.min.js'
            },
            "site": {
                "src": [
                    'jsonp.js',
                    'src/*.js'

                ],
                "dest": 'test/lib/<%= pkg.name %>.min.js'
            }
        },
        "watch": {
            "scripts": {
                "files": ['src/*.js'],
                "tasks": ['compile'],
                "options": {
                    "spawn": false,
                }
            }
        },
        copy: {
            site: {
                expand: true,
                cwd: 'test',
                src: '**',
                dest: 'public/'
            }
        }
    };

    grunt.initConfig(gruntConfig);
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-copy');
    // Compile web site
    grunt.registerTask('compile', ['clean', 'uglify', 'copy']);
    grunt.registerTask('default', ['compile']);

};<commit_msg>fixed build references<commit_after>module.exports = function(grunt) {

    var gruntConfig = {

        "clean": {
            "content": ['dist/*', 'public/*']
        },

        "pkg": grunt.file.readJSON('package.json'),
        "uglify": {
            "options": {
                "banner": '/*! <%= pkg.name %> <%= pkg.version %> <%= grunt.template.today("yyyy-mm-dd") %> */',
                "wrap": true,
                "sourceMap": true,
                "sourceMapIncludeSources": true,
                "sourceMapName": 'dist/<%= pkg.name %>.min.js.map'
            },
            "build": {
                "src": [
                    'jsonp.js',
                    'src/*.js'

                ],
                "dest": 'dist/<%= pkg.name %>.min.js'
            },
            "site": {
                "src": [
                    'jsonp.js',
                    'src/*.js'

                ],
                "dest": 'test/lib/<%= pkg.name %>.min.js'
            }
        },
        "watch": {
            "scripts": {
                "files": ['src/*.js'],
                "tasks": ['compile'],
                "options": {
                    "spawn": false,
                }
            }
        },
        copy: {
            site: {
                expand: true,
                cwd: 'test',
                src: '**',
                dest: 'public/'
            }
        }
    };

    grunt.initConfig(gruntConfig);
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-copy');
    // Compile web site
    grunt.registerTask('compile', ['clean', 'uglify', 'copy']);
    grunt.registerTask('default', ['compile']);

};<|endoftext|>


<commit_before>!function() {

   let pbp = function() {};
   var fs               = require('fs');
   var umo              = require('./matchObject');
   var d3Dsv            = require('d3-dsv');
   var chardet          = require('chardet');
   var removeDiacritics = require('diacritics').remove;
   var ProgressBar      = require('progress');

   pbp.validateArchive = function(archive_name) {
      let matches = d3Dsv.csvParse(pbp.loadFile(archive_name));
      let errors = pbp.validateMatchArray(matches);
      let valid = matches.length - errors.length;
      let pct_valid = (valid / matches.length).toFixed(2) * 100;
      console.log(`Valid Matches: ${valid} (${pct_valid}%), Invalid Matches: ${errors.length}`);
      return errors;
   }

   pbp.loadFile = function(file_name) {
      var targetFile = file_name;
      var chard = chardet.detectFileSync(targetFile);
      var encoding = (chard.indexOf('ISO') >= 0 || chard == 'UTF-8' || chard == 'windows-1252') ? 'utf8' : 'utf16le';
      return fs.readFileSync(targetFile, encoding);
   }

   pbp.validateMatchArray = function(match_array) {
      var results = [];
      var bar = new ProgressBar(':bar', { total: match_array.length });
      for (var i=0; i < match_array.length; i++) {
         results.push({ i, errors: pbp.validateMatch(match_array[i]).errors });
         bar.tick();
      }
      return results.filter(f=>f.errors.length);
   }

   pbp.writeValidArchive = function(source, destination) {
      let matches = d3Dsv.csvParse(pbp.loadFile(source));
      let errors = pbp.validateMatchArray(matches);
      let invalid_matches = errors.map(m=>m.i);
      let valid_rows = matches.filter((m, i) => invalid_matches.indexOf(i) < 0);
      if (valid_rows.length) {
         let keys = Object.keys(valid_rows[0]);
         let header = keys.join(',');
         let rows = valid_rows.map(row => { return keys.map(k => row[k]).join(','); });
         let data = [].concat(header, ...rows).join('\r\n');
         fs.writeFileSync(destination, data);
         return true;
      }
      return false;
   }

   pbp.validateMatch = function(row) {
      let errors = [];
      var match = {};
      var winner = parseInt(row.winner) - 1;
      var player_array = [];
      player_array.push(removeDiacritics(row.server1));
      player_array.push(removeDiacritics(row.server2));

      var sets_won = [0, 0];
      var scores = row.score.split(' ');
      var score = [];
      for (var c=0; c < scores.length; c++) {
         var tiebreak_score = scores[c].indexOf('(') >= 0 ? scores[c].split('(')[1].split(')')[0] : undefined;
         if (winner == 0) {
            var player0_score = scores[c].split('-')[0];
            var player1_score = scores[c].split('-')[1].split('(')[0];
         } else {
            var player1_score = scores[c].split('-')[0];
            var player0_score = scores[c].split('-')[1].split('(')[0];
         }
         if (player0_score > player1_score) {
            sets_won[0] +=1;
         } else {
            sets_won[1] +=1;
         }
         score.push({ '0': player0_score, '1': player1_score, tiebreak: tiebreak_score });
      }

      let format = 'AdSetsTo6tb7';
      var score_progression = [];
      var sets = row.pbp.split('.').filter(s => s);    // filter out empty sets
      var valid_match = true;

      for (var s=0; s < sets.length; s++) {
         if (sets[s] == '' || !score[s]) { continue; } // Blank Set; No Score
         if (s == 4 && (score[4][0] > 7 || score[4][1] > 7)) format = 'longSetTo6by2';
         var result = pbp.validSet(sets[s], format);
         if (!result.complete) {
            errors.push('incomplete set');
            valid_match = false;
         } else {
            score_progression.push(result.score);
         }
      }
      var validation = validateScore(score, winner, score_progression);
      if (valid_match) {
         if (validation.error) {
            errors.push(validation.error);
         }
      } else {
         errors.push('invalid match');
      }

      return { errors };
   }

   pbp.validSet = function(points, format) {
      points = points.split(';').join('').split('/').join('');
      let set = umo.Set({type: format});
      set.addPoints(points);
      return { complete: set.complete(), score: set.scoreboard() };
   }

   function validateScore(score, winner, score_progression) {
      if (score.length != score_progression.length) {
         return { error: 'Discrepancy in number of Sets', error_code: 0 };
      }
      for (var s=0; s < score.length; s++) {

         if (score[s].player0 > 7 || score[s].player1 > 7) {
            return { error: 'Erroneous Score', error_code: 5 };
         }

         var set_score = score_progression[s];
         if (!set_score) return { error: 'No Score', error_code: 1 };

         var tiebreak = undefined;
         var player0_score = set_score.split('-')[0];
         var player1_score = set_score.split('-')[1].split('(')[0].trim();
         if (set_score.indexOf('(') > 0) { tiebreak = set_score.split('(')[1].split(')')[0]; }

         if (tiebreak != score[s].tiebreak) {
            return { error: 'Tiebreak Mismatch', error_code: 3 };
         }
         if (score[s].player0 == player0_score && score[s].player1 != player1_score) { return { error: 'Score mismatch', error_code: 4 }; }
         if (score[s].player1 == player1_score && score[s].player0 != player0_score) { return { error: 'Score mismatch', error_code: 4 }; }
         if (score[s].player0 == player1_score && score[s].player1 != player0_score) { return { error: 'Score mismatch', error_code: 4 }; }
         if (score[s].player1 == player0_score && score[s].player0 != player1_score) { return { error: 'Score mismatch', error_code: 4 }; }
      }
      return {};
   }

   if (typeof define === "function" && define.amd) define(pbp); else if (typeof module === "object" && module.exports) module.exports = pbp;
   this.pbp = pbp;

}();
<commit_msg>fix to support grand slam qualifying format (3rd set long)<commit_after>!function() {

   let pbp = function() {};
   var fs               = require('fs');
   var umo              = require('./matchObject');
   var d3Dsv            = require('d3-dsv');
   var chardet          = require('chardet');
   var removeDiacritics = require('diacritics').remove;
   var ProgressBar      = require('progress');

   pbp.validateArchive = function(archive_name) {
      let matches = d3Dsv.csvParse(pbp.loadFile(archive_name));
      let errors = pbp.validateMatchArray(matches);
      let valid = matches.length - errors.length;
      let pct_valid = (valid / matches.length).toFixed(2) * 100;
      console.log(`Valid Matches: ${valid} (${pct_valid}%), Invalid Matches: ${errors.length}`);
      return errors;
   }

   pbp.loadFile = function(file_name) {
      var targetFile = file_name;
      var chard = chardet.detectFileSync(targetFile);
      var encoding = (chard.indexOf('ISO') >= 0 || chard == 'UTF-8' || chard == 'windows-1252') ? 'utf8' : 'utf16le';
      return fs.readFileSync(targetFile, encoding);
   }

   pbp.validateMatchArray = function(match_array) {
      var results = [];
      var bar = new ProgressBar(':bar', { total: match_array.length });
      for (var i=0; i < match_array.length; i++) {
         results.push({ i, errors: pbp.validateMatch(match_array[i]).errors });
         bar.tick();
      }
      return results.filter(f=>f.errors.length);
   }

   pbp.writeValidArchive = function(source, destination) {
      let matches = d3Dsv.csvParse(pbp.loadFile(source));
      let errors = pbp.validateMatchArray(matches);
      let invalid_matches = errors.map(m=>m.i);
      let valid_rows = matches.filter((m, i) => invalid_matches.indexOf(i) < 0);
      if (valid_rows.length) {
         let keys = Object.keys(valid_rows[0]);
         let header = keys.join(',');
         let rows = valid_rows.map(row => { return keys.map(k => row[k]).join(','); });
         let data = [].concat(header, ...rows).join('\r\n');
         fs.writeFileSync(destination, data);
         return true;
      }
      return false;
   }

   pbp.validateMatch = function(row) {
      let errors = [];
      var match = {};
      var winner = parseInt(row.winner) - 1;
      var player_array = [];
      player_array.push(removeDiacritics(row.server1));
      player_array.push(removeDiacritics(row.server2));

      var sets_won = [0, 0];
      var scores = row.score.split(' ');
      var score = [];
      for (var c=0; c < scores.length; c++) {
         var tiebreak_score = scores[c].indexOf('(') >= 0 ? scores[c].split('(')[1].split(')')[0] : undefined;
         if (winner == 0) {
            var player0_score = scores[c].split('-')[0];
            var player1_score = scores[c].split('-')[1].split('(')[0];
         } else {
            var player1_score = scores[c].split('-')[0];
            var player0_score = scores[c].split('-')[1].split('(')[0];
         }
         if (player0_score > player1_score) {
            sets_won[0] +=1;
         } else {
            sets_won[1] +=1;
         }
         score.push({ '0': player0_score, '1': player1_score, tiebreak: tiebreak_score });
      }

      let format = 'AdSetsTo6tb7';
      var score_progression = [];
      var sets = row.pbp.split('.').filter(s => s);    // filter out empty sets
      var valid_match = true;

      for (var s=0; s < sets.length; s++) {
         if (sets[s] == '' || !score[s]) { continue; } // Blank Set; No Score
         if (score[s][0] > 7 || score[s][1] > 7) format = 'longSetTo6by2';
         var result = pbp.validSet(sets[s], format);
         if (!result.complete) {
            errors.push('incomplete set');
            valid_match = false;
         } else {
            score_progression.push(result.score);
         }
      }
      var validation = validateScore(score, winner, score_progression);
      if (valid_match) {
         if (validation.error) {
            errors.push(validation.error);
         }
      } else {
         errors.push('invalid match');
      }

      return { errors };
   }

   pbp.validSet = function(points, format) {
      points = points.split(';').join('').split('/').join('');
      let set = umo.Set({type: format});
      set.addPoints(points);
      return { complete: set.complete(), score: set.scoreboard() };
   }

   function validateScore(score, winner, score_progression) {
      if (score.length != score_progression.length) {
         return { error: 'Discrepancy in number of Sets', error_code: 0 };
      }
      for (var s=0; s < score.length; s++) {

         if (score[s].player0 > 7 || score[s].player1 > 7) {
            return { error: 'Erroneous Score', error_code: 5 };
         }

         var set_score = score_progression[s];
         if (!set_score) return { error: 'No Score', error_code: 1 };

         var tiebreak = undefined;
         var player0_score = set_score.split('-')[0];
         var player1_score = set_score.split('-')[1].split('(')[0].trim();
         if (set_score.indexOf('(') > 0) { tiebreak = set_score.split('(')[1].split(')')[0]; }

         if (tiebreak != score[s].tiebreak) {
            return { error: 'Tiebreak Mismatch', error_code: 3 };
         }
         if (score[s].player0 == player0_score && score[s].player1 != player1_score) { return { error: 'Score mismatch', error_code: 4 }; }
         if (score[s].player1 == player1_score && score[s].player0 != player0_score) { return { error: 'Score mismatch', error_code: 4 }; }
         if (score[s].player0 == player1_score && score[s].player1 != player0_score) { return { error: 'Score mismatch', error_code: 4 }; }
         if (score[s].player1 == player0_score && score[s].player0 != player1_score) { return { error: 'Score mismatch', error_code: 4 }; }
      }
      return {};
   }

   if (typeof define === "function" && define.amd) define(pbp); else if (typeof module === "object" && module.exports) module.exports = pbp;
   this.pbp = pbp;

}();
<|endoftext|>