<commit_before>$(window).load(function() {

  var threeColumnContentCalled = false;
  var windowWidthMark = 1180;

  var preElements = $('.content').find('pre');

  // fix css for three column layout
  threeColumnContent();

  $(window).resize(function() {
    // fix css for three column layout
    if (!threeColumnContentCalled) {
	    threeColumnContent();
    }
    hideScrollbarMoz();
  });

  // testing
  function hideScrollbarMoz() {
  	var cW, sW;
  	$.each(preElements, function(i, pre) {
      cW = pre.clientWidth,
  	  sW = pre.scrollWidth;
  	  $(pre).find('.scrolls-x').removeClass('scrolls-x');
  	  if (cW != sW) {
  	  	$(pre).addClass('scrolls-x');
  	  } else {
  	  	//if ($(pre).hasClass('scrolls-x').removeClass('scroll-x'));
  	  }

  	});
  };

  hideScrollbarMoz();

  // fix for
 elements floated to right for third column layout
  // each
 element gets floated right
  // special case
 followed by one or more
 tags,
  // jump the each in this case for all but the first

  //
  // want each element before
 tags to have total height (height + margin and padding)
  // to be same as floated
 at right
  function threeColumnContent() {
    // if not needed, return
  	if ($(window).width() < windowWidthMark) {
      return;
  	} else {
  	  threeColumnContentCalled = true;
  	}

    $.each(preElements, function(i, preElement) {

      var $this_pre = $(preElement);

      // get previous sibling of this pre element
      var $previous = $this_pre.prev();

      // if previous elements is
, jump each as it's allready accounted for
      if (isPre($previous)) {
      	return;
      }

      // get measures
      // total height of preElement
      var this_pre_heights = getHeights($this_pre);

      // total height of previous to this preElement
      var previous_heights = getHeights($previous);

      // get next sibling for case
 is followed by one or more
 elements
      var $next = $this_pre.next();

      // calculate pre heights
      // top measures don't affect
      // if only one pre element, total height to consider if paddings are the same, inner height
      var this_pre_height = this_pre_heights.inner_height;
      var previous_height = previous_heights.inner_height;

      // case
 is followed by one or more

      // if more then one pre element, sum of inner heights and 'inner' paddings
      if (isPre($next.prop('nodeName'))) {

        this_pre_height = this_pre_height + this_pre_heights.padding_bottom;
      	var next_pre_heights = getHeights($next);

      	while (isPre($next.prop('nodeName'))) {
          this_pre_height = this_pre_height + next_pre_heights.inner_height + this_pre_heights.padding_top;
          $next = $next.next();
        }

        // if previous height < pre_height
        if (previous_height < this_pre_height) {
          // set -margin and padding to compensate float empty space
          $previous.css('margin-bottom', - (this_pre_height - previous_heights.inner_height));
          $previous.css('padding-bottom', (this_pre_height - previous_heights.inner_height + previous_heights.padding_bottom));
        }

      } else {

      	// if previous height < pre_height
        if (previous_height < this_pre_height) {
          // set -margin and padding to compensate float empty space
          $previous.css('margin-bottom', - (this_pre_height - previous_heights.inner_height));
          $previous.css('padding-bottom', (this_pre_height - previous_heights.inner_height + previous_heights.padding_bottom));
        }

      }
    });

  	// return true if is pre element
  	function isPre(nodeName) {
  	  return ($(nodeName).prop('nodeName') === 'PRE');
  	}

  	// return heights of element: inner height, padding-top, padding-bottom
  	function getHeights(elem) {
  	  var h = {};

  	  h.inner_height = $(elem).height();
  	  h.padding_bottom = parseInt($(elem).css('padding-bottom'));
  	  h.padding_top = parseInt($(elem).css('padding-top'));

  	  return h;
  	}
  }
});<commit_msg>refactor main.js<commit_after>$(window).load(function() {

  var threeColumnContentCalled = false;
  var minWidth_threeColumn = 1180;
  var ww = $(window).width();

  var preElements = $('.content').find('pre');

  if (ww > minWidth_threeColumn) {
    // fix css for three column layout
    threeColumnCss();
  }

  $(window).resize(function() { console.log('in resize');
    // new window width
    ww = $(window).width();
    if (!threeColumnContentCalled && (ww > minWidth_threeColumn)) {
      threeColumnCss();
    }
    //hideScrollbarMoz();
  });

  // --------------------------------------------------------------------- hideScrollbarMoz
  // testing
  function hideScrollbarMoz() {
  	var cW, sW;
  	$.each(preElements, function(i, pre) {
      cW = pre.clientWidth,
  	  sW = pre.scrollWidth;
  	  $(pre).find('.scrolls-x').removeClass('scrolls-x');
  	  if (cW != sW) {
  	  	$(pre).addClass('scrolls-x');
  	  } else {
  	  	//if ($(pre).hasClass('scrolls-x').removeClass('scroll-x'));
  	  }

  	});
  };

  //hideScrollbarMoz();

  // ----------------------------------------------------------------------- threeColumnCss
  // fix css for three column layout (fill gap)
  // each
 element gets floated right and leaves 'empty' background space
  // special case
 followed by one or more
 tags,
  // jump the each in this case for all but the first

  //
  // want each element before
 tags to have total height (height + margin and padding)
  // to be same as floated
 at right
  function threeColumnCss() {

  	threeColumnContentCalled = true;

    $.each(preElements, function(i, preElement) {

      var $this_pre = $(preElement);
      var $previous = $this_pre.prev();
      var $next = $this_pre.next();

      // if previous elements is
, jump each as it's allready accounted for
      if (isPre($previous)) return;

      // get heights
      var this_pre_heights = getHeights($this_pre);
      var previous_heights = getHeights($previous);

      // calculate gap to fill
      // top measures don't affect
      // if only one pre element, total height to consider if paddings are the same is the inner height
      var fillHeight = this_pre_heights.inner_height;

      // case
 is followed by one or more

      // if more then one pre element, sum of inner heights and 'inner' paddings
      if (isPre($next)) {

        // include padding between this and next element
        fillHeight += this_pre_heights.padding_bottom;

      	while (isPre($next)) {
          fillHeight +=  $next.height() + this_pre_heights.padding_top;
          $next = $next.next();
        }
      }

      if (previous_heights.inner_height < fillHeight) {
        // set -margin and padding to compensate float empty space
        $previous.css('margin-bottom', -(fillHeight - previous_heights.inner_height));
        $previous.css('padding-bottom', (fillHeight - previous_heights.inner_height + previous_heights.padding_bottom));
      }
    });

  	// return true if elem is pre element
  	function isPre(elem) {
  	  return ($(elem).prop('nodeName') === 'PRE');
  	}

  	// return heights of element
  	function getHeights(elem) {
  	  return {
        inner_height: $(elem).height(),
        padding_bottom: parseInt($(elem).css('padding-bottom')),
        padding_top: parseInt($(elem).css('padding-top'))
      };
  	}
  }
});<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const fs = require('fs');
const handlebars = require('handlebars');

class HTMLReporter {
  constructor(options) {
    options = options || {};

    this.output = options.output || path.join(process.cwd(), 'dumpinator-report.html');

    this.counter = {
      passed: 0,
      failed: 0,
      get total() {
        return this.passed + this.failed;
      }
    };

    this.tests = [];
  }

  report(notify) {
    notify.on('test.add', (test) => {
      this.tests.push(test);
    });

    notify.on('test.finish', (test) => {
      if (test.state === 'passed') {
        this.counter.passed += 1;
      } else {
        this.counter.failed += 1;
      }
    });

    notify.on('finish', () => {
      this.createReport(notify.session);
    });
  }

  createReport(data) {
    const html = handlebars.compile(fs.readFileSync(path.join(__dirname, '../../templates/html-report.hbs'), { encoding: 'utf8' }));
    fs.writeFileSync(this.output, html({
      tests: this.tests,
      counter: this.counter
    }));
  }

  diff(diff) {
    // if (diff.type === 'error') {
    //   if (diff.testFiles) {
    //     console.log(diff.testFiles.join('\n')); // eslint-disable-line no-console
    //   }
    //
    //   return;
    // }
    //
    // this.drawDiff('header', diff.headerDiff);
    // this.drawDiff('body', diff.bodyDiff);
  }

  drawDiff(type, diff) {
    // let lineNumbersLeft = 1;
    // let lineNumbersRight = 1;
    // const colored = cf();
    // const title = type === 'body' ? '[ BODY ]' : '[ HEAD ]';
    //
    // colored.txt(`${title}`).nl();
    //
    // const diffMap = diff.map((line, index, arr) => {
    //   line.prev = index ? arr[index - 1].line : [];
    //   line.next = index < (arr.length - 1) ? arr[index + 1].value.replace(/\n$/, '').split(/\n/g) : [];
    //   line.line = line.value.replace(/\n$/, '').split(/\n/g);
    //
    //   return line;
    // });
    //
    // diffMap.forEach((line) => {
    //   if (line.added) {
    //     line.line.forEach((l, index, array) => {
    //       colored.txt('  ', 'ltrim').txt('|');
    //       colored.txt((`  ${lineNumbersRight}`).substr(-2, 2), 'ltrim').txt('|');
    //       this.drawInlineDiff(colored, l, line.prev[index] || '', 'bglime', 'bggreen');
    //       colored.nl();
    //       lineNumbersRight += 1;
    //     });
    //   } else if (line.removed) {
    //     line.line.forEach((l, index, array) => {
    //       colored.txt((`  ${lineNumbersLeft}`).substr(-2, 2), 'ltrim').txt('|');
    //       colored.txt('  ', 'ltrim').txt('|');
    //       this.drawInlineDiff(colored, l, line.next[index] || '', 'bgfire', 'bgred');
    //       colored.nl();
    //       lineNumbersLeft += 1;
    //     });
    //   } else {
    //     line.line.forEach((l, index, array) => {
    //       if (!this.showFullDiff && index > 3 && index === array.length - 3) {
    //         colored.txt(('··'), 'ltrim').txt('|');
    //         colored.txt(('··'), 'ltrim').txt('|');
    //         colored.nl();
    //       }
    //
    //       if (this.showFullDiff || (index < 3 || index > array.length - 4)) {
    //         colored.txt((`  ${lineNumbersLeft}`).substr(-2, 2), 'ltrim').txt('|');
    //         colored.txt((`  ${lineNumbersRight}`).substr(-2, 2), 'ltrim').txt('|');
    //         colored.txt(l, 'trim').nl();
    //       }
    //
    //       lineNumbersLeft += 1;
    //       lineNumbersRight += 1;
    //     });
    //   }
    // });
    //
    // if (diffMap.length === 1 && !diffMap.added && !diffMap.removed) {
    //   colored.nl().green(' ✔').grey('both responses are the same').nl();
    // } else {
    //   let numDifferences = 0;
    //   diffMap.forEach((line) => {
    //     if (line.added) {
    //       numDifferences += 1;
    //     }
    //   });
    //   colored.nl().red(' ❌').grey([`${numDifferences} difference in the ${type} found`, `${numDifferences} differences in the ${type} found`, numDifferences]).nl();
    // }
    //
    // colored.print();
  }
}

module.exports = HTMLReporter;
<commit_msg>Clean code<commit_after>'use strict';

const path = require('path');
const fs = require('fs');
const handlebars = require('handlebars');

class HTMLReporter {
  constructor(options) {
    options = options || {};

    this.output = options.output || path.join(process.cwd(), 'dumpinator-report.html');

    this.counter = {
      passed: 0,
      failed: 0,
      get total() {
        return this.passed + this.failed;
      }
    };

    this.tests = [];
  }

  report(notify) {
    notify.on('test.add', (test) => {
      this.tests.push(test);
    });

    notify.on('test.finish', (test) => {
      if (test.state === 'passed') {
        this.counter.passed += 1;
      } else {
        this.counter.failed += 1;
      }
    });

    notify.on('finish', () => {
      this.createReport(notify.session);
    });
  }

  createReport(data) {
    const html = handlebars.compile(fs.readFileSync(path.join(__dirname, '../../templates/html-report.hbs'), { encoding: 'utf8' }));
    fs.writeFileSync(this.output, html({
      tests: this.tests,
      counter: this.counter
    }));
  }

  diff(diff) {

  }
}

module.exports = HTMLReporter;
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 */

'use strict';

const GlobalTransformCache = require('../lib/GlobalTransformCache');
const TransformCache = require('../lib/TransformCache');

const crypto = require('crypto');
const docblock = require('./DependencyGraph/docblock');
const fs = require('fs');
const invariant = require('invariant');
const isAbsolutePath = require('absolute-path');
const jsonStableStringify = require('json-stable-stringify');

const {join: joinPath, relative: relativePath, extname} = require('path');

import type {TransformedCode, Options as TransformOptions} from '../JSTransformer/worker/worker';
import type {SourceMap} from '../lib/SourceMap';
import type {ReadTransformProps} from '../lib/TransformCache';
import type {Reporter} from '../lib/reporting';
import type Cache from './Cache';
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
import type ModuleCache from './ModuleCache';

/**
 * If the global cache returns empty that many times, we give up using the
 * global cache for that instance. This speeds up the build.
 */
const GLOBAL_CACHE_MAX_MISSES = 250;

type ReadResult = {
  code: string,
  dependencies?: ?Array<string>,
  dependencyOffsets?: ?Array<number>,
  map?: ?SourceMap,
  source: string,
};

export type TransformCode = (
  module: Module,
  sourceCode: string,
  transformOptions: TransformOptions,
) => Promise<TransformedCode>;

export type Options = {
  resetCache?: boolean,
  cacheTransformResults?: boolean,
};

export type ConstructorArgs = {
  file: string,
  moduleCache: ModuleCache,
  cache: Cache,
  transformCode: ?TransformCode,
  transformCacheKey: ?string,
  depGraphHelpers: DependencyGraphHelpers,
  options: Options,
  reporter: Reporter,
};

class Module {

  path: string;
  type: string;

  _moduleCache: ModuleCache;
  _cache: Cache;
  _transformCode: ?TransformCode;
  _transformCacheKey: ?string;
  _depGraphHelpers: DependencyGraphHelpers;
  _options: Options;
  _reporter: Reporter;

  _docBlock: Promise<{id?: string, moduleDocBlock: {[key: string]: mixed}}>;
  _readSourceCodePromise: Promise<string>;
  _readPromises: Map<string, Promise<ReadResult>>;

  static _globalCacheRetries: number;
  static _globalCacheMaxMisses: number;

  constructor({
    file,
    moduleCache,
    cache,
    transformCode,
    transformCacheKey,
    depGraphHelpers,
    reporter,
    options,
  }: ConstructorArgs) {
    if (!isAbsolutePath(file)) {
      throw new Error('Expected file to be absolute path but got ' + file);
    }

    this.path = file;
    this.type = 'Module';

    this._moduleCache = moduleCache;
    this._cache = cache;
    this._transformCode = transformCode;
    this._transformCacheKey = transformCacheKey;
    invariant(
      transformCode == null || transformCacheKey != null,
      'missing transform cache key',
    );
    this._depGraphHelpers = depGraphHelpers;
    this._options = options || {};
    this._reporter = reporter;

    this._readPromises = new Map();
  }

  isHaste(): Promise<boolean> {
    return this._cache.get(
      this.path,
      'isHaste',
      () => this._readDocBlock().then(({id}) => !!id)
    );
  }

  getCode(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({code}) => code);
  }

  getMap(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({map}) => map);
  }

  getName(): Promise<string> {
    return this._cache.get(
      this.path,
      'name',
      () => this._readDocBlock().then(({id}) => {
        if (id) {
          return id;
        }

        const p = this.getPackage();

        if (!p) {
          // Name is full path
          return this.path;
        }

        return p.getName()
          .then(name => {
            if (!name) {
              return this.path;
            }

            return joinPath(name, relativePath(p.root, this.path)).replace(/\\/g, '/');
          });
      })
    );
  }

  getPackage() {
    return this._moduleCache.getPackageForModule(this);
  }

  getDependencies(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({dependencies}) => dependencies);
  }

  /**
   * We don't need to invalidate the TranformCache itself because it guarantees
   * itself that if a source code changed we won't return the cached transformed
   * code.
   */
  invalidate() {
    this._cache.invalidate(this.path);
    this._readPromises.clear();
  }

  _parseDocBlock(docBlock) {
    // Extract an id for the module if it's using @providesModule syntax
    // and if it's NOT in node_modules (and not a whitelisted node_module).
    // This handles the case where a project may have a dep that has @providesModule
    // docblock comments, but doesn't want it to conflict with whitelisted @providesModule
    // modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
    // project-specific code that is using @providesModule.
    const moduleDocBlock = docblock.parseAsObject(docBlock);
    const provides = moduleDocBlock.providesModule || moduleDocBlock.provides;

    const id = provides && !this._depGraphHelpers.isNodeModulesDir(this.path)
        ? /^\S+/.exec(provides)[0]
        : undefined;
    return {id, moduleDocBlock};
  }

  _readSourceCode() {
    if (!this._readSourceCodePromise) {
      this._readSourceCodePromise = new Promise(
        resolve => resolve(fs.readFileSync(this.path, 'utf8'))
      );
    }
    return this._readSourceCodePromise;
  }

  _readDocBlock() {
    if (!this._docBlock) {
      this._docBlock = this._readSourceCode()
        .then(docBlock => this._parseDocBlock(docBlock));
    }
    return this._docBlock;
  }

  /**
   * To what we read from the cache or worker, we need to add id and source.
   */
  _finalizeReadResult(
    source: string,
    id?: string,
    extern: boolean,
    result: TransformedCode,
  ): ReadResult {
    if (this._options.cacheTransformResults === false) {
      const {dependencies} = result;
      /* $FlowFixMe: this code path is dead, remove. */
      return {dependencies};
    }
    return {...result, id, source};
  }

  _transformCodeForCallback(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    const {_transformCode} = this;
    invariant(_transformCode != null, 'missing code transform funtion');
    const {sourceCode, transformOptions} = cacheProps;
    return _transformCode(this, sourceCode, transformOptions).then(
      freshResult => process.nextTick(callback, undefined, freshResult),
      error => process.nextTick(callback, error),
    );
  }

  _transformAndStoreCodeGlobally(
    cacheProps: ReadTransformProps,
    globalCache: GlobalTransformCache,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    this._transformCodeForCallback(
      cacheProps,
      (transformError, transformResult) => {
        if (transformError != null) {
          callback(transformError);
          return;
        }
        invariant(
          transformResult != null,
          'Inconsistent state: there is no error, but no results either.',
        );
        globalCache.store(cacheProps, transformResult);
        callback(undefined, transformResult);
      },
    );
  }

  _getTransformedCode(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    const globalCache = GlobalTransformCache.get();
    const noMoreRetries = Module._globalCacheRetries <= 0;
    const tooManyMisses = Module._globalCacheMaxMisses <= 0;
    if (globalCache == null || noMoreRetries || tooManyMisses) {
      this._transformCodeForCallback(cacheProps, callback);
      return;
    }
    globalCache.fetch(cacheProps, (globalCacheError, globalCachedResult) => {
      if (globalCacheError != null && Module._globalCacheRetries > 0) {
        this._reporter.update({
          type: 'global_cache_error',
          error: globalCacheError,
        });
        Module._globalCacheRetries--;
        if (Module._globalCacheRetries <= 0) {
          this._reporter.update({
            type: 'global_cache_disabled',
            reason: 'too_many_errors',
          });
        }
      }
      if (globalCachedResult == null) {
        --Module._globalCacheMaxMisses;
        if (Module._globalCacheMaxMisses === 0) {
          this._reporter.update({
            type: 'global_cache_disabled',
            reason: 'too_many_misses',
          });
        }
        this._transformAndStoreCodeGlobally(cacheProps, globalCache, callback);
        return;
      }
      if (Module._globalCacheMaxMisses < GLOBAL_CACHE_MAX_MISSES) {
        ++Module._globalCacheMaxMisses;
      }
      callback(undefined, globalCachedResult);
    });
  }

  _getAndCacheTransformedCode(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    this._getTransformedCode(cacheProps, (error, result) => {
      if (error) {
        callback(error);
        return;
      }
      invariant(result != null, 'missing result');
      TransformCache.writeSync({...cacheProps, result});
      callback(undefined, result);
    });
  }

  /**
   * Read everything about a module: source code, transformed code,
   * dependencies, etc. The overall process is to read the cache first, and if
   * it's a miss, we let the worker write to the cache and read it again.
   */
  read(transformOptions: TransformOptions): Promise<ReadResult> {
    const key = stableObjectHash(transformOptions || {});
    const promise = this._readPromises.get(key);
    if (promise != null) {
      return promise;
    }
    const freshPromise = Promise.all([
      this._readSourceCode(),
      this._readDocBlock(),
    ]).then(([sourceCode, {id, moduleDocBlock}]) => {
      // Ignore requires in JSON files or generated code. An example of this
      // is prebuilt files like the SourceMap library.
      const extern = this.isJSON() || 'extern' in moduleDocBlock;
      if (extern) {
        transformOptions = {...transformOptions, extern};
      }
      const transformCacheKey = this._transformCacheKey;
      invariant(transformCacheKey != null, 'missing transform cache key');
      const cacheProps = {
        filePath: this.path,
        sourceCode,
        transformCacheKey,
        transformOptions,
        cacheOptions: this._options,
      };
      const cachedResult = TransformCache.readSync(cacheProps);
      if (cachedResult) {
        return Promise.resolve(this._finalizeReadResult(sourceCode, id, extern, cachedResult));
      }
      return new Promise((resolve, reject) => {
        this._getAndCacheTransformedCode(
          cacheProps,
          (transformError, freshResult) => {
            if (transformError) {
              reject(transformError);
              return;
            }
            invariant(freshResult != null, 'inconsistent state');
            resolve(this._finalizeReadResult(sourceCode, id, extern, freshResult));
          },
        );
      });
    });
    this._readPromises.set(key, freshPromise);
    return freshPromise;
  }

  hash() {
    return `Module : ${this.path}`;
  }

  isJSON() {
    return extname(this.path) === '.json';
  }

  isAsset() {
    return false;
  }

  isPolyfill() {
    return false;
  }

  toJSON() {
    return {
      hash: this.hash(),
      isJSON: this.isJSON(),
      isAsset: this.isAsset(),
      type: this.type,
      path: this.path,
    };
  }
}

Module._globalCacheRetries = 4;
Module._globalCacheMaxMisses = GLOBAL_CACHE_MAX_MISSES;

// use weak map to speed up hash creation of known objects
const knownHashes = new WeakMap();
function stableObjectHash(object) {
  let digest = knownHashes.get(object);
  if (!digest) {
    digest = crypto.createHash('md5')
      .update(jsonStableStringify(object))
      .digest('base64');
    knownHashes.set(object, digest);
  }

  return digest;
}

module.exports = Module;
<commit_msg>packager: Module: remove too-many-misses codepath<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 */

'use strict';

const GlobalTransformCache = require('../lib/GlobalTransformCache');
const TransformCache = require('../lib/TransformCache');

const crypto = require('crypto');
const docblock = require('./DependencyGraph/docblock');
const fs = require('fs');
const invariant = require('invariant');
const isAbsolutePath = require('absolute-path');
const jsonStableStringify = require('json-stable-stringify');

const {join: joinPath, relative: relativePath, extname} = require('path');

import type {TransformedCode, Options as TransformOptions} from '../JSTransformer/worker/worker';
import type {SourceMap} from '../lib/SourceMap';
import type {ReadTransformProps} from '../lib/TransformCache';
import type {Reporter} from '../lib/reporting';
import type Cache from './Cache';
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
import type ModuleCache from './ModuleCache';

type ReadResult = {
  code: string,
  dependencies?: ?Array<string>,
  dependencyOffsets?: ?Array<number>,
  map?: ?SourceMap,
  source: string,
};

export type TransformCode = (
  module: Module,
  sourceCode: string,
  transformOptions: TransformOptions,
) => Promise<TransformedCode>;

export type Options = {
  resetCache?: boolean,
  cacheTransformResults?: boolean,
};

export type ConstructorArgs = {
  file: string,
  moduleCache: ModuleCache,
  cache: Cache,
  transformCode: ?TransformCode,
  transformCacheKey: ?string,
  depGraphHelpers: DependencyGraphHelpers,
  options: Options,
  reporter: Reporter,
};

class Module {

  path: string;
  type: string;

  _moduleCache: ModuleCache;
  _cache: Cache;
  _transformCode: ?TransformCode;
  _transformCacheKey: ?string;
  _depGraphHelpers: DependencyGraphHelpers;
  _options: Options;
  _reporter: Reporter;

  _docBlock: Promise<{id?: string, moduleDocBlock: {[key: string]: mixed}}>;
  _readSourceCodePromise: Promise<string>;
  _readPromises: Map<string, Promise<ReadResult>>;

  static _globalCacheRetries: number;

  constructor({
    file,
    moduleCache,
    cache,
    transformCode,
    transformCacheKey,
    depGraphHelpers,
    reporter,
    options,
  }: ConstructorArgs) {
    if (!isAbsolutePath(file)) {
      throw new Error('Expected file to be absolute path but got ' + file);
    }

    this.path = file;
    this.type = 'Module';

    this._moduleCache = moduleCache;
    this._cache = cache;
    this._transformCode = transformCode;
    this._transformCacheKey = transformCacheKey;
    invariant(
      transformCode == null || transformCacheKey != null,
      'missing transform cache key',
    );
    this._depGraphHelpers = depGraphHelpers;
    this._options = options || {};
    this._reporter = reporter;

    this._readPromises = new Map();
  }

  isHaste(): Promise<boolean> {
    return this._cache.get(
      this.path,
      'isHaste',
      () => this._readDocBlock().then(({id}) => !!id)
    );
  }

  getCode(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({code}) => code);
  }

  getMap(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({map}) => map);
  }

  getName(): Promise<string> {
    return this._cache.get(
      this.path,
      'name',
      () => this._readDocBlock().then(({id}) => {
        if (id) {
          return id;
        }

        const p = this.getPackage();

        if (!p) {
          // Name is full path
          return this.path;
        }

        return p.getName()
          .then(name => {
            if (!name) {
              return this.path;
            }

            return joinPath(name, relativePath(p.root, this.path)).replace(/\\/g, '/');
          });
      })
    );
  }

  getPackage() {
    return this._moduleCache.getPackageForModule(this);
  }

  getDependencies(transformOptions: TransformOptions) {
    return this.read(transformOptions).then(({dependencies}) => dependencies);
  }

  /**
   * We don't need to invalidate the TranformCache itself because it guarantees
   * itself that if a source code changed we won't return the cached transformed
   * code.
   */
  invalidate() {
    this._cache.invalidate(this.path);
    this._readPromises.clear();
  }

  _parseDocBlock(docBlock) {
    // Extract an id for the module if it's using @providesModule syntax
    // and if it's NOT in node_modules (and not a whitelisted node_module).
    // This handles the case where a project may have a dep that has @providesModule
    // docblock comments, but doesn't want it to conflict with whitelisted @providesModule
    // modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
    // project-specific code that is using @providesModule.
    const moduleDocBlock = docblock.parseAsObject(docBlock);
    const provides = moduleDocBlock.providesModule || moduleDocBlock.provides;

    const id = provides && !this._depGraphHelpers.isNodeModulesDir(this.path)
        ? /^\S+/.exec(provides)[0]
        : undefined;
    return {id, moduleDocBlock};
  }

  _readSourceCode() {
    if (!this._readSourceCodePromise) {
      this._readSourceCodePromise = new Promise(
        resolve => resolve(fs.readFileSync(this.path, 'utf8'))
      );
    }
    return this._readSourceCodePromise;
  }

  _readDocBlock() {
    if (!this._docBlock) {
      this._docBlock = this._readSourceCode()
        .then(docBlock => this._parseDocBlock(docBlock));
    }
    return this._docBlock;
  }

  /**
   * To what we read from the cache or worker, we need to add id and source.
   */
  _finalizeReadResult(
    source: string,
    id?: string,
    extern: boolean,
    result: TransformedCode,
  ): ReadResult {
    if (this._options.cacheTransformResults === false) {
      const {dependencies} = result;
      /* $FlowFixMe: this code path is dead, remove. */
      return {dependencies};
    }
    return {...result, id, source};
  }

  _transformCodeForCallback(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    const {_transformCode} = this;
    invariant(_transformCode != null, 'missing code transform funtion');
    const {sourceCode, transformOptions} = cacheProps;
    return _transformCode(this, sourceCode, transformOptions).then(
      freshResult => process.nextTick(callback, undefined, freshResult),
      error => process.nextTick(callback, error),
    );
  }

  _transformAndStoreCodeGlobally(
    cacheProps: ReadTransformProps,
    globalCache: GlobalTransformCache,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    this._transformCodeForCallback(
      cacheProps,
      (transformError, transformResult) => {
        if (transformError != null) {
          callback(transformError);
          return;
        }
        invariant(
          transformResult != null,
          'Inconsistent state: there is no error, but no results either.',
        );
        globalCache.store(cacheProps, transformResult);
        callback(undefined, transformResult);
      },
    );
  }

  _getTransformedCode(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    const globalCache = GlobalTransformCache.get();
    const noMoreRetries = Module._globalCacheRetries <= 0;
    if (globalCache == null || noMoreRetries) {
      this._transformCodeForCallback(cacheProps, callback);
      return;
    }
    globalCache.fetch(cacheProps, (globalCacheError, globalCachedResult) => {
      if (globalCacheError != null && Module._globalCacheRetries > 0) {
        this._reporter.update({
          type: 'global_cache_error',
          error: globalCacheError,
        });
        Module._globalCacheRetries--;
        if (Module._globalCacheRetries <= 0) {
          this._reporter.update({
            type: 'global_cache_disabled',
            reason: 'too_many_errors',
          });
        }
      }
      if (globalCachedResult == null) {
        this._transformAndStoreCodeGlobally(cacheProps, globalCache, callback);
        return;
      }
      callback(undefined, globalCachedResult);
    });
  }

  _getAndCacheTransformedCode(
    cacheProps: ReadTransformProps,
    callback: (error: ?Error, result: ?TransformedCode) => void,
  ) {
    this._getTransformedCode(cacheProps, (error, result) => {
      if (error) {
        callback(error);
        return;
      }
      invariant(result != null, 'missing result');
      TransformCache.writeSync({...cacheProps, result});
      callback(undefined, result);
    });
  }

  /**
   * Read everything about a module: source code, transformed code,
   * dependencies, etc. The overall process is to read the cache first, and if
   * it's a miss, we let the worker write to the cache and read it again.
   */
  read(transformOptions: TransformOptions): Promise<ReadResult> {
    const key = stableObjectHash(transformOptions || {});
    const promise = this._readPromises.get(key);
    if (promise != null) {
      return promise;
    }
    const freshPromise = Promise.all([
      this._readSourceCode(),
      this._readDocBlock(),
    ]).then(([sourceCode, {id, moduleDocBlock}]) => {
      // Ignore requires in JSON files or generated code. An example of this
      // is prebuilt files like the SourceMap library.
      const extern = this.isJSON() || 'extern' in moduleDocBlock;
      if (extern) {
        transformOptions = {...transformOptions, extern};
      }
      const transformCacheKey = this._transformCacheKey;
      invariant(transformCacheKey != null, 'missing transform cache key');
      const cacheProps = {
        filePath: this.path,
        sourceCode,
        transformCacheKey,
        transformOptions,
        cacheOptions: this._options,
      };
      const cachedResult = TransformCache.readSync(cacheProps);
      if (cachedResult) {
        return Promise.resolve(this._finalizeReadResult(sourceCode, id, extern, cachedResult));
      }
      return new Promise((resolve, reject) => {
        this._getAndCacheTransformedCode(
          cacheProps,
          (transformError, freshResult) => {
            if (transformError) {
              reject(transformError);
              return;
            }
            invariant(freshResult != null, 'inconsistent state');
            resolve(this._finalizeReadResult(sourceCode, id, extern, freshResult));
          },
        );
      });
    });
    this._readPromises.set(key, freshPromise);
    return freshPromise;
  }

  hash() {
    return `Module : ${this.path}`;
  }

  isJSON() {
    return extname(this.path) === '.json';
  }

  isAsset() {
    return false;
  }

  isPolyfill() {
    return false;
  }

  toJSON() {
    return {
      hash: this.hash(),
      isJSON: this.isJSON(),
      isAsset: this.isAsset(),
      type: this.type,
      path: this.path,
    };
  }
}

Module._globalCacheRetries = 4;

// use weak map to speed up hash creation of known objects
const knownHashes = new WeakMap();
function stableObjectHash(object) {
  let digest = knownHashes.get(object);
  if (!digest) {
    digest = crypto.createHash('md5')
      .update(jsonStableStringify(object))
      .digest('base64');
    knownHashes.set(object, digest);
  }

  return digest;
}

module.exports = Module;
<|endoftext|>


<commit_before>var CronJob = require('cron').CronJob;
var request = require("request");
var mongoose = require("mongoose");
mongoose.Promise = require('bluebird');

var url = "https://poloniex.com/public?command=returnTicker";

var mongodbUri = "mongodb://localhost/jpdanta";
var mongodbOptions = {
  useMongoClient: true,
  socketTimeoutMS: 0,
  keepAlive: true,
  reconnectTries: 30
};

function log(msg) {
    var date = new Date();
    console.log(date.toLocaleString() + " " + msg);
}

function transform_ticker(whenFetched, tickerjson) {
    var t_ticker = [];
//    var colnames = ["", "last", "lowestAsk", "highestBid", "percentChange", "baseVolume", "quoteVolume", "high24hr", "low24hr"]
    var colnames = ["", "last", "lowestAsk", "highestBid"]

    // var coinids = [];
    // var measureids = [];

    // colnames.forEach(function(value, x) {
    //     if (value != "") {
    //         measureids.push({"id": x, "name": value});
    //     }
    // });

    for (var i in tickerjson) {
        // per coin
        // coinids.push({"id": tickerjson[i]["id"], "name": i});
        colnames.forEach(function (value, x) {
            if (value != "") {
                t_ticker.push({
                    a: tickerjson[i]["id"], // coin id
                    b: x, // measure
                    c: tickerjson[i][value], // value
                    d: whenFetched // whenFetched
                });

            }
        });
    }

    // {
    //     var fs = require('fs');
    //     console.log(measureids);
    //     console.log(coinids);
    //     fs.writeFileSync("measureids.txt", JSON.stringify(measureids));
    //     fs.writeFileSync("coinids.txt", JSON.stringify(coinids));
    // }
    return t_ticker;
}

var Schema = mongoose.Schema;
var tickerSchema = new Schema({
    a: {
        type: Number,
        required: true
    },
    b: {
        type: Number,
        required: true
    },
    c: {
        type: Number,
        required: true
    },
    d: {
        type: Date,
        required: true
    },
});

module.exports = mongoose.model('ticker', tickerSchema);

function requestfn(error, response, body) {
    // log("got into response");
    if (error) {
        console.error(error);
        return;
    }
    var date = new Date();
    var ticker2;
    try {
        ticker2 = transform_ticker(date, JSON.parse(body));
    } catch (error) {
        console.error(error);
        return;
    }

    var db = mongoose.connection;
    // db.on('error', console.error);
    // db.once('open', function () {
    //     //console.log("Connected to mongodb");
    // });

    mongoose.connect(mongodbUri, mongodbOptions);
    // log("mongoose connected");
    var Ticker = mongoose.model('ticker', tickerSchema);

    ticker2.forEach(function (aTicker, x) {
        var aTickerObj = new Ticker(aTicker);
        aTickerObj.save(function (err, doc) {
            if (err) throw err;
        });
    });

    mongoose.disconnect();
    // log("mongoose disconnected");
}

new CronJob('*/3 * * * * *', function () {
    // log("start");
    request(url, requestfn);
    // log("finish");
}, null, true);<commit_msg>successfully merged<commit_after>var CronJob = require('cron').CronJob;
var request = require("request");
var mongoose = require("mongoose");
mongoose.Promise = require('bluebird');

var url = "https://poloniex.com/public?command=returnTicker";

var mongodbUri = "mongodb://localhost/jpdanta";
var mongodbOptions = {
  useMongoClient: true,
  socketTimeoutMS: 0,
  keepAlive: true,
  reconnectTries: 30
};

function log(msg) {
    var date = new Date();
    console.log(date.toLocaleString() + " " + msg);
}

function transform_ticker(whenFetched, tickerjson) {
    var t_ticker = [];
//    var colnames = ["", "last", "lowestAsk", "highestBid", "percentChange", "baseVolume", "quoteVolume", "high24hr", "low24hr"]
    var colnames = ["", "last", "lowestAsk", "highestBid"]

    // var coinids = [];
    // var measureids = [];

    // colnames.forEach(function(value, x) {
    //     if (value != "") {
    //         measureids.push({"id": x, "name": value});
    //     }
    // });

    for (var i in tickerjson) {
        // per coin
        // coinids.push({"id": tickerjson[i]["id"], "name": i});
        colnames.forEach(function (value, x) {
            if (value != "") {
                t_ticker.push({
                    a: tickerjson[i]["id"], // coin id
                    b: x, // measure
                    c: tickerjson[i][value], // value
                    d: whenFetched // whenFetched
                });

            }
        });
    }

    // {
    //     var fs = require('fs');
    //     console.log(measureids);
    //     console.log(coinids);
    //     fs.writeFileSync("measureids.txt", JSON.stringify(measureids));
    //     fs.writeFileSync("coinids.txt", JSON.stringify(coinids));
    // }
    return t_ticker;
}

var Schema = mongoose.Schema;
var tickerSchema = new Schema({
    a: {
        type: Number,
        required: true
    },
    b: {
        type: Number,
        required: true
    },
    c: {
        type: Number,
        required: true
    },
    d: {
        type: Date,
        required: true
    },
});

module.exports = mongoose.model('ticker', tickerSchema);

function requestfn(error, response, body) {
    // log("got into response");
    if (error) {
        console.error(error);
        return;
    }
    var date = new Date();
    var ticker2;
    try {
        ticker2 = transform_ticker(date, JSON.parse(body));
    } catch (error) {
        console.error(error);
        return;
    }

    var db = mongoose.connection;
    // db.on('error', console.error);
    // db.once('open', function () {
    //     //console.log("Connected to mongodb");
    // });

    mongoose.connect(mongodbUri, mongodbOptions);
    // log("mongoose connected");
    var Ticker = mongoose.model('ticker', tickerSchema);

    ticker2.forEach(function (aTicker, x) {
        var aTickerObj = new Ticker(aTicker);
        aTickerObj.save(function (err, doc) {
            if (err) throw err;
        });
    });

    mongoose.disconnect();
    // log("mongoose disconnected");
}

new CronJob('*/10 * * * * *', function () {
    // log("start");
    request(url, requestfn);
    // log("finish");
}, null, true);<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import Paper from 'material-ui/Paper';
import styled from 'styled-components';
import { connect } from 'react-redux';
import { trim } from 'lodash';
import { PhoneNumberUtil } from 'google-libphonenumber';
import { compose, pure, withPropsOnChange, withHandlers, getContext } from 'recompose';
import TextField from 'material-ui/TextField';
import IconButton from 'material-ui/IconButton';
import CallIcon from 'material-ui-icons/Call';
import CallEndIcon from 'material-ui-icons/CallEnd';
import { CALL_STATUS_IDLE, CALL_STATUS_STARTING, CALL_STATUS_ACTIVE } from 'react-sip';
import { CONFERENCE_PHONE_NUMBER } from './../../src/redux/dialer/constants';

const phoneUtil = PhoneNumberUtil.getInstance();

const Wrapper = styled(Paper).attrs({
  elevation: 0,
})`
  display: flex;
  flex-grow: 1;
  align-items: center;
  justify-content: center;
  padding-top: 10px;
`;
const CallForm = styled.div`
  max-width: 600px;
  display: flex;
  align-items: center;
`;
const ActionButtonWrapper = styled.div`width: 40px;`;

const Dialer = ({
  phoneNumber,
  phoneNumberIsValid,
  phoneNumberIsEmpty,
  onPhoneNumberChange,
  onPhoneNumberFocus,
  onPhoneNumberKeyDown,
  onStartButtonClick,
  onStopButtonClick,
  callStatus,
  helperText,
}) =>
  (<Wrapper>
    <CallForm>
      <TextField
        label={callStatus === CALL_STATUS_IDLE ? 'Who shall we call?' : ' '}
        placeholder="e.g. +44 000 000-00-00"
        error={!phoneNumberIsEmpty && !phoneNumberIsValid}
        helperText={helperText}
        value={phoneNumber}
        disabled={callStatus !== CALL_STATUS_IDLE}
        InputProps={{
          onChange: onPhoneNumberChange,
          onFocus: onPhoneNumberFocus,
          onKeyDown: onPhoneNumberKeyDown,
        }}
      />
      <ActionButtonWrapper>
        {callStatus === CALL_STATUS_IDLE
          ? <IconButton
            color={phoneNumberIsEmpty || !phoneNumberIsValid ? undefined : 'primary'}
            disabled={phoneNumberIsEmpty || !phoneNumberIsValid}
            onClick={onStartButtonClick}
          >
            <CallIcon />
          </IconButton>
          : null}
        {callStatus === CALL_STATUS_ACTIVE
          ? <IconButton color="primary" onClick={onStopButtonClick}>
            <CallEndIcon />
          </IconButton>
          : null}
      </ActionButtonWrapper>
    </CallForm>
  </Wrapper>);

export default compose(
  getContext({
    sipStart: PropTypes.func,
    sipAnswer: PropTypes.func,
    sipStop: PropTypes.func,
    callStatus: PropTypes.string,
  }),
  connect(
    (state) => state.dialer,
    (dispatch) => ({
      setPhoneNumber: (value) =>
        dispatch({
          type: 'dialer/SET_PHONE_NUMBER',
          value,
        }),
      addToCallLog: (entry) =>
        dispatch({
          type: 'callLog/ADD',
          entry,
        }),
    }),
  ),
  withPropsOnChange(['phoneNumber'], ({ phoneNumber }) => {
    const phoneNumberIsEmpty = trim(phoneNumber) === '';
    let phoneNumberIsValid = false;
    if (phoneNumber.replace(/\s/g, '') === CONFERENCE_PHONE_NUMBER) {
      phoneNumberIsValid = true;
    } else if (!phoneNumberIsEmpty) {
      try {
        const phoneNumberProto = phoneUtil.parse(phoneNumber, 'UK');
        phoneNumberIsValid = phoneUtil.isValidNumber(phoneNumberProto);
      } catch (e) {
        /* eslint-disable-line no-empty */
      }
    }
    return {
      phoneNumberIsValid,
      phoneNumberIsEmpty,
    };
  }),
  withPropsOnChange(['callStatus'], ({ callStatus }) => {
    let helperText = ' ';
    if (callStatus === CALL_STATUS_STARTING) {
      helperText = 'dialing...';
    }
    if (callStatus === CALL_STATUS_ACTIVE) {
      helperText = 'on air!';
    }
    return {
      helperText,
    };
  }),
  withHandlers({
    onPhoneNumberChange: ({ setPhoneNumber }) => (e) => {
      setPhoneNumber(e.target.value);
    },
    onPhoneNumberFocus: ({ callStatus }) => (e) => {
      const target = e.target;
      setTimeout(() => {
        if (callStatus === CALL_STATUS_IDLE && target) {
          target.select();
        }
      }, 50);
    },
    onPhoneNumberKeyDown: ({
      callStatus,
      phoneNumberIsValid,
      phoneNumber,
      sipStart,
      addToCallLog,
    }) => (e) => {
      if (e.which === 13) {
        // enter
        if (callStatus === CALL_STATUS_IDLE && phoneNumberIsValid) {
          sipStart(phoneNumber);
          addToCallLog({ phoneNumber, startTimestamp: +new Date() });
        }
      }
    },
    onStartButtonClick: ({
      sipStart,
      callStatus,
      phoneNumberIsValid,
      phoneNumber,
      addToCallLog,
    }) => () => {
      if (callStatus === CALL_STATUS_IDLE && phoneNumberIsValid) {
        sipStart(phoneNumber);
        addToCallLog({ phoneNumber, startTimestamp: +new Date() });
      }
    },
    onStopButtonClick: ({ sipStop, callStatus }) => () => {
      if (callStatus === CALL_STATUS_ACTIVE) {
        sipStop();
      }
    },
  }),
  pure,
)(Dialer);
<commit_msg>implemented phone number verification and normalisation<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import Paper from 'material-ui/Paper';
import styled from 'styled-components';
import { connect } from 'react-redux';
import { trim } from 'lodash';
import { PhoneNumberUtil, PhoneNumberFormat } from 'google-libphonenumber';
import {
  compose,
  pure,
  withPropsOnChange,
  withHandlers,
  getContext,
} from 'recompose';
import TextField from 'material-ui/TextField';
import IconButton from 'material-ui/IconButton';
import CallIcon from 'material-ui-icons/Call';
import CallEndIcon from 'material-ui-icons/CallEnd';
import {
  CALL_STATUS_IDLE,
  CALL_STATUS_STARTING,
  CALL_STATUS_ACTIVE,
} from 'react-sip';
import { CONFERENCE_PHONE_NUMBER } from './../../src/redux/dialer/constants';

const phoneUtil = PhoneNumberUtil.getInstance();

const Wrapper = styled(Paper).attrs({
  elevation: 0,
})`
  display: flex;
  flex-grow: 1;
  align-items: center;
  justify-content: center;
  padding-top: 10px;
`;
const CallForm = styled.div`
  max-width: 600px;
  display: flex;
  align-items: center;
`;
const ActionButtonWrapper = styled.div`width: 40px;`;

const Dialer = ({
  phoneNumber,
  phoneNumberIsValid,
  phoneNumberIsEmpty,
  onPhoneNumberChange,
  onPhoneNumberFocus,
  onPhoneNumberKeyDown,
  onStartButtonClick,
  onStopButtonClick,
  callStatus,
  helperText,
}) => (
  <Wrapper>
    <CallForm>
      <TextField
        label={callStatus === CALL_STATUS_IDLE ? 'Who shall we call?' : ' '}
        placeholder="e.g. +44 000 000-00-00"
        error={!phoneNumberIsEmpty && !phoneNumberIsValid}
        helperText={helperText}
        value={phoneNumber}
        disabled={callStatus !== CALL_STATUS_IDLE}
        InputProps={{
          onChange: onPhoneNumberChange,
          onFocus: onPhoneNumberFocus,
          onKeyDown: onPhoneNumberKeyDown,
        }}
      />
      <ActionButtonWrapper>
        {callStatus === CALL_STATUS_IDLE ? (
          <IconButton
            color={
              phoneNumberIsEmpty || !phoneNumberIsValid ? undefined : 'primary'
            }
            disabled={phoneNumberIsEmpty || !phoneNumberIsValid}
            onClick={onStartButtonClick}
          >
            <CallIcon />
          </IconButton>
        ) : null}
        {callStatus === CALL_STATUS_ACTIVE ? (
          <IconButton color="primary" onClick={onStopButtonClick}>
            <CallEndIcon />
          </IconButton>
        ) : null}
      </ActionButtonWrapper>
    </CallForm>
  </Wrapper>
);

export default compose(
  getContext({
    sipStart: PropTypes.func,
    sipAnswer: PropTypes.func,
    sipStop: PropTypes.func,
    callStatus: PropTypes.string,
  }),
  connect(
    (state) => state.dialer,
    (dispatch) => ({
      setPhoneNumber: (value) =>
        dispatch({
          type: 'dialer/SET_PHONE_NUMBER',
          value,
        }),
      addToCallLog: (entry) =>
        dispatch({
          type: 'callLog/ADD',
          entry,
        }),
    }),
  ),
  withPropsOnChange(['phoneNumber'], ({ phoneNumber }) => {
    const phoneNumberIsEmpty = trim(phoneNumber) === '';
    let phoneNumberIsValid = false;
    if (phoneNumber.replace(/\s/g, '') === CONFERENCE_PHONE_NUMBER) {
      phoneNumberIsValid = true;
    } else if (!phoneNumberIsEmpty) {
      try {
        const phoneNumberProto = phoneUtil.parse(phoneNumber, 'UK');
        phoneNumberIsValid = phoneUtil.isValidNumber(phoneNumberProto);
      } catch (e) {
        /* eslint-disable-line no-empty */
      }
    }
    return {
      phoneNumberIsValid,
      phoneNumberIsEmpty,
    };
  }),
  withPropsOnChange(['callStatus'], ({ callStatus }) => {
    let helperText = ' ';
    if (callStatus === CALL_STATUS_STARTING) {
      helperText = 'dialing...';
    }
    if (callStatus === CALL_STATUS_ACTIVE) {
      helperText = 'on air!';
    }
    return {
      helperText,
    };
  }),
  withHandlers({
    startCallIfNeeded: ({
      callStatus,
      phoneNumberIsValid,
      phoneNumber,
      setPhoneNumber,
      sipStart,
      addToCallLog,
    }) => () => {
      if (callStatus === CALL_STATUS_IDLE && phoneNumberIsValid) {
        let phoneNumberForSip;
        let phoneNumberForLog;
        if (phoneNumber.replace(/\s/g, '') === CONFERENCE_PHONE_NUMBER) {
          phoneNumberForSip = CONFERENCE_PHONE_NUMBER;
          phoneNumberForLog = CONFERENCE_PHONE_NUMBER;
        } else {
          phoneNumberForSip = phoneUtil.format(
            phoneUtil.parse(phoneNumber, 'UK'),
            PhoneNumberFormat.E164,
          );
          phoneNumberForLog = phoneUtil.format(
            phoneUtil.parse(phoneNumber, 'UK'),
            PhoneNumberFormat.INTERNATIONAL,
          );
        }
        setPhoneNumber(phoneNumberForLog);
        sipStart(phoneNumberForSip);
        addToCallLog({
          phoneNumber: phoneNumberForLog,
          startTimestamp: +new Date(),
        });
      }
    },
  }),
  withHandlers({
    onPhoneNumberChange: ({ setPhoneNumber }) => (e) => {
      setPhoneNumber(e.target.value);
    },
    onPhoneNumberFocus: ({ callStatus }) => (e) => {
      const target = e.target;
      setTimeout(() => {
        if (callStatus === CALL_STATUS_IDLE && target) {
          target.select();
        }
      }, 50);
    },
    onPhoneNumberKeyDown: ({ startCallIfNeeded }) => (e) => {
      if (e.which === 13) {
        // enter
        startCallIfNeeded();
      }
    },
    onStartButtonClick: ({ startCallIfNeeded }) => () => {
      startCallIfNeeded();
    },
    onStopButtonClick: ({ sipStop, callStatus }) => () => {
      if (callStatus === CALL_STATUS_ACTIVE) {
        sipStop();
      }
    },
  }),
  pure,
)(Dialer);
<|endoftext|>


<commit_before>var krb = { };

// 5.2.1.  KerberosString
krb.KerberosString = asn1.GeneralString;  // TODO: IA5String restriction

// 5.2.4.  Constrained Integer Types
krb.Int32 = asn1.INTEGER.rangeConstrained(-2147483648, 2147483647);
krb.UInt32 = asn1.INTEGER.rangeConstrained(0, 4294967295);
krb.Microseconds = asn1.INTEGER.rangeConstrained(0, 999999);

// 5.2.2.  Realm and PrincipalName
krb.Realm = krb.KerberosString;
krb.PrincipalName = new asn1.SEQUENCE(
    [{id: 'nameType', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'nameString',
      type: new asn1.SEQUENCE_OF(krb.KerberosString).tagged(asn1.tag(1))}]);

// 5.2.3.  KerberosTime
krb.KerberosTime = asn1.GeneralizedTime.constrained(function (date) {
    if (date.getUTCMilliseconds() != 0)
        throw "Milliseconds not allowed in KerberosTime";
});

// 5.2.5.  HostAddress and HostAddresses
krb.HostAddress = new asn1.SEQUENCE(
    [{id: 'addrType', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'address', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]);
krb.HostAddresses = new asn1.SEQUENCE_OF(krb.HostAddress);

// 5.2.6.  AuthorizationData
krb.AuthorizationData = new asn1.SEQUENCE_OF(
    new asn1.SEQUENCE(
        [{id: 'adType', type: krb.Int32.tagged(asn1.tag(0))},
         {id: 'adData', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]));

// 5.2.6.1.  IF-RELEVANT
krb.AD_IF_RELEVANT = krb.AuthorizationData;

// 5.2.9.  Cryptosystem-Related Types
krb.EncryptedData = new asn1.SEQUENCE(
    [{id: 'etype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'kvno', type: krb.UInt32.tagged(asn1.tag(1)), optional: true},
     {id: 'cipher', type: asn1.OCTET_STRING.tagged(asn1.tag(2))}]);
krb.EncryptionKey = new asn1.SEQUENCE(
    [{id: 'keytype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'keyvalue', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]);
krb.Checksum = new asn1.SEQUENCE(
    [{id: 'cksumtype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'checksum', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]);

// 5.2.6.2.  KDCIssued
krb.AD_KDCIssued = new asn1.SEQUENCE(
    [{id: 'adChecksum', type: krb.Checksum.tagged(asn1.tag(0))},
     {id: 'iRealm', type: krb.Realm.tagged(asn1.tag(1)), optional: true},
     {id: 'iSname', type: krb.PrincipalName.tagged(asn1.tag(2)),
      optional: true},
     {id: 'elements', type: krb.AuthorizationData.tagged(asn1.tag(3))}]);

// 5.2.6.3.  AND-OR
krb.AD_AND_OR = new asn1.SEQUENCE(
    [{id: 'conditionCount', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'elements', type: krb.AuthorizationData.tagged(asn1.tag(1))}]);

// 5.2.6.4.  MANDATORY-FOR-KDC
krb.AD_MANDATORY_FOR_KDC = krb.AuthorizationData;

// 5.2.7.  PA-DATA
krb.PA_DATA = new asn1.SEQUENCE(
    [{id: 'padataType', type: krb.Int32.tagged(asn1.tag(1))},
     {id: 'padataValue', type: asn1.OCTET_STRING.tagged(asn1.tag(2))}]);

// 5.2.7.2.  Encrypted Timestamp Pre-authentication
krb.PA_ENC_TIMESTAMP = krb.EncryptedData;
krb.PA_ENC_TS_ENC = new asn1.SEQUENCE(
    [{id: 'patimestamp', type: krb.KerberosTime.tagged(asn1.tag(0))},
     {id: 'pausec', type: krb.Microseconds.tagged(asn1.tag(1)),
      optional: true}]);

// 5.2.7.4.  PA-ETYPE-INFO
krb.ETYPE_INFO_ENTRY = new asn1.SEQUENCE(
    [{id: 'etype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'salt', type: asn1.OCTET_STRING.tagged(asn1.tag(1)),
      optional: true}]);
krb.ETYPE_INFO = new asn1.SEQUENCE_OF(krb.ETYPE_INFO_ENTRY);

// 5.2.7.5.  PA-ETYPE-INFO2
krb.ETYPE_INFO2_ENTRY = new asn1.SEQUENCE(
    [{id: 'etype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'salt', type: krb.KerberosString.tagged(asn1.tag(1)),
      optional: true},
     {id: 's2kparams', type: asn1.OCTET_STRING.tagged(asn1.tag(2))}]);
krb.ETYPE_INFO2 = new asn1.SEQUENCE_OF(krb.ETYPE_INFO2_ENTRY);

// 5.2.8.  KerberosFlags
krb.KerberosFlags = asn1.BIT_STRING.constrained(function (bs) {
    if (bs.length < 32)
        throw "Invalid KerberosFlags";
});

// 5.3.  Tickets
krb.Ticket = new asn1.SEQUENCE(
    [{id: 'tktVno', type: asn1.INTEGER.valueConstrained(5).tagged(asn1.tag(0))},
     {id: 'realm', type: krb.Realm.tagged(asn1.tag(1))},
     {id: 'sname', type: krb.PrincipalName.tagged(asn1.tag(2))},
     {id: 'encPart', type: krb.EncryptedData.tagged(asn1.tag(3))}]
).tagged(asn1.tag(1, asn1.TAG_CONSTRUCTED, asn1.TAG_APPLICATION));
krb.TicketFlags = krb.KerberosFlags;
krb.TransitedEncoding = new asn1.SEQUENCE(
    [{id: 'trType', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'contents', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]);
krb.EncTicketPart = new asn1.SEQUENCE(
    [{id: 'flags', type: krb.TicketFlags.tagged(asn1.tag(0))},
     {id: 'key', type: krb.EncryptionKey.tagged(asn1.tag(1))},
     {id: 'crealm', type: krb.Realm.tagged(asn1.tag(2))},
     {id: 'cname', type: krb.PrincipalName.tagged(asn1.tag(3))},
     {id: 'transited', type: krb.TransitedEncoding.tagged(asn1.tag(4))},
     {id: 'authtime', type: krb.KerberosTime.tagged(asn1.tag(5))},
     {id: 'starttime', type: krb.KerberosTime.tagged(asn1.tag(6)),
      optional: true},
     {id: 'endtime', type: krb.KerberosTime.tagged(asn1.tag(7))},
     {id: 'renewTill', type: krb.KerberosTime.tagged(asn1.tag(8)),
      optional: true},
     {id: 'caddr', type: krb.HostAddresses.tagged(asn1.tag(9)),
      optional: true},
     {id: 'authorizationData', type: krb.AuthorizationData.tagged(asn1.tag(10)),
      optional: true}]
).tagged(asn1.tag(3, asn1.TAG_CONSTRUCTED, asn1.TAG_APPLICATION));

// 5.4.1.  KRB_KDC_REQ Definition
krb.KDCOptions = krb.KerberosFlags;
krb.KDC_REQ_BODY = new asn1.SEQUENCE(
    [{id: 'kdcOptions', type: krb.KDCOptions.tagged(asn1.tag(0))},
     {id: 'principalName', type: krb.PrincipalName.tagged(asn1.tag(1)),
      optional: true},
     {id: 'realm', type: krb.Realm.tagged(asn1.tag(2))},
     {id: 'sname', type: krb.PrincipalName.tagged(asn1.tag(3)),
      optional: true},
     {id: 'from', type: krb.KerberosTime.tagged(asn1.tag(4)),
      optional: true},
     {id: 'till', type: krb.KerberosTime.tagged(asn1.tag(5))},
     {id: 'rtime', type: krb.KerberosTime.tagged(asn1.tag(6)),
      optional: true},
     {id: 'nonce', type: krb.UInt32.tagged(asn1.tag(7))},
     {id: 'etype', type: new asn1.SEQUENCE_OF(krb.Int32).tagged(asn1.tag(8))},
     {id: 'addresses', type: krb.HostAddresses.tagged(asn1.tag(9)),
      optional: true},
     {id: 'encAuthorizationData', type: krb.EncryptedData.tagged(asn1.tag(10)),
      optional: true},
     {id: 'additionalTickets',
      type: new asn1.SEQUENCE_OF(krb.Ticket).tagged(asn1.tag(10)),
      optional: true}]);
krb.KDC_REQ = new asn1.SEQUENCE(
    [{id: 'pvno', type: asn1.INTEGER.valueConstrained(5).tagged(asn1.tag(1))},
     {id: 'msgType',
      type: asn1.INTEGER.valueConstrained(10, 12).tagged(asn1.tag(2))},
     {id: 'padata',
      type: new asn1.SEQUENCE_OF(krb.PA_DATA).tagged(asn1.tag(3)),
      optional: true},
     {id: 'reqBody', type: krb.KDC_REQ_BODY.tagged(asn1.tag(4))}]);
krb.AS_REQ = krb.KDC_REQ.tagged(asn1.tag(10, asn1.TAG_CONSTRUCTED,
                                         asn1.TAG_APPLICATION));
krb.TGS_REQ = krb.KDC_REQ.tagged(asn1.tag(12, asn1.TAG_CONSTRUCTED,
                                         asn1.TAG_APPLICATION));

// TODO: 5.4.2.  KRB_KDC_REP Definition

// TODO: 5.5.1.  KRB_AP_REQ Definition

// TODO: 5.5.2.  KRB_AP_REP Definition

// TODO: 5.6.1.  KRB_SAFE Definition

// TODO: 5.7.1.  KRB_PRIV Definition

// TODO: 5.8.1.  KRB_CRED Definition

// TODO: 5.9.1.  KRB_ERROR Definition<commit_msg>KRB_KDC_REP definitions<commit_after>var krb = { };

// 5.2.1.  KerberosString
krb.KerberosString = asn1.GeneralString;  // TODO: IA5String restriction

// 5.2.4.  Constrained Integer Types
krb.Int32 = asn1.INTEGER.rangeConstrained(-2147483648, 2147483647);
krb.UInt32 = asn1.INTEGER.rangeConstrained(0, 4294967295);
krb.Microseconds = asn1.INTEGER.rangeConstrained(0, 999999);

// 5.2.2.  Realm and PrincipalName
krb.Realm = krb.KerberosString;
krb.PrincipalName = new asn1.SEQUENCE(
    [{id: 'nameType', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'nameString',
      type: new asn1.SEQUENCE_OF(krb.KerberosString).tagged(asn1.tag(1))}]);

// 5.2.3.  KerberosTime
krb.KerberosTime = asn1.GeneralizedTime.constrained(function (date) {
    if (date.getUTCMilliseconds() != 0)
        throw "Milliseconds not allowed in KerberosTime";
});

// 5.2.5.  HostAddress and HostAddresses
krb.HostAddress = new asn1.SEQUENCE(
    [{id: 'addrType', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'address', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]);
krb.HostAddresses = new asn1.SEQUENCE_OF(krb.HostAddress);

// 5.2.6.  AuthorizationData
krb.AuthorizationData = new asn1.SEQUENCE_OF(
    new asn1.SEQUENCE(
        [{id: 'adType', type: krb.Int32.tagged(asn1.tag(0))},
         {id: 'adData', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]));

// 5.2.6.1.  IF-RELEVANT
krb.AD_IF_RELEVANT = krb.AuthorizationData;

// 5.2.9.  Cryptosystem-Related Types
krb.EncryptedData = new asn1.SEQUENCE(
    [{id: 'etype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'kvno', type: krb.UInt32.tagged(asn1.tag(1)), optional: true},
     {id: 'cipher', type: asn1.OCTET_STRING.tagged(asn1.tag(2))}]);
krb.EncryptionKey = new asn1.SEQUENCE(
    [{id: 'keytype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'keyvalue', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]);
krb.Checksum = new asn1.SEQUENCE(
    [{id: 'cksumtype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'checksum', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]);

// 5.2.6.2.  KDCIssued
krb.AD_KDCIssued = new asn1.SEQUENCE(
    [{id: 'adChecksum', type: krb.Checksum.tagged(asn1.tag(0))},
     {id: 'iRealm', type: krb.Realm.tagged(asn1.tag(1)), optional: true},
     {id: 'iSname', type: krb.PrincipalName.tagged(asn1.tag(2)),
      optional: true},
     {id: 'elements', type: krb.AuthorizationData.tagged(asn1.tag(3))}]);

// 5.2.6.3.  AND-OR
krb.AD_AND_OR = new asn1.SEQUENCE(
    [{id: 'conditionCount', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'elements', type: krb.AuthorizationData.tagged(asn1.tag(1))}]);

// 5.2.6.4.  MANDATORY-FOR-KDC
krb.AD_MANDATORY_FOR_KDC = krb.AuthorizationData;

// 5.2.7.  PA-DATA
krb.PA_DATA = new asn1.SEQUENCE(
    [{id: 'padataType', type: krb.Int32.tagged(asn1.tag(1))},
     {id: 'padataValue', type: asn1.OCTET_STRING.tagged(asn1.tag(2))}]);

// 5.2.7.2.  Encrypted Timestamp Pre-authentication
krb.PA_ENC_TIMESTAMP = krb.EncryptedData;
krb.PA_ENC_TS_ENC = new asn1.SEQUENCE(
    [{id: 'patimestamp', type: krb.KerberosTime.tagged(asn1.tag(0))},
     {id: 'pausec', type: krb.Microseconds.tagged(asn1.tag(1)),
      optional: true}]);

// 5.2.7.4.  PA-ETYPE-INFO
krb.ETYPE_INFO_ENTRY = new asn1.SEQUENCE(
    [{id: 'etype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'salt', type: asn1.OCTET_STRING.tagged(asn1.tag(1)),
      optional: true}]);
krb.ETYPE_INFO = new asn1.SEQUENCE_OF(krb.ETYPE_INFO_ENTRY);

// 5.2.7.5.  PA-ETYPE-INFO2
krb.ETYPE_INFO2_ENTRY = new asn1.SEQUENCE(
    [{id: 'etype', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'salt', type: krb.KerberosString.tagged(asn1.tag(1)),
      optional: true},
     {id: 's2kparams', type: asn1.OCTET_STRING.tagged(asn1.tag(2))}]);
krb.ETYPE_INFO2 = new asn1.SEQUENCE_OF(krb.ETYPE_INFO2_ENTRY);

// 5.2.8.  KerberosFlags
krb.KerberosFlags = asn1.BIT_STRING.constrained(function (bs) {
    if (bs.length < 32)
        throw "Invalid KerberosFlags";
});

// 5.3.  Tickets
krb.Ticket = new asn1.SEQUENCE(
    [{id: 'tktVno', type: asn1.INTEGER.valueConstrained(5).tagged(asn1.tag(0))},
     {id: 'realm', type: krb.Realm.tagged(asn1.tag(1))},
     {id: 'sname', type: krb.PrincipalName.tagged(asn1.tag(2))},
     {id: 'encPart', type: krb.EncryptedData.tagged(asn1.tag(3))}]
).tagged(asn1.tag(1, asn1.TAG_CONSTRUCTED, asn1.TAG_APPLICATION));
krb.TicketFlags = krb.KerberosFlags;
krb.TransitedEncoding = new asn1.SEQUENCE(
    [{id: 'trType', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'contents', type: asn1.OCTET_STRING.tagged(asn1.tag(1))}]);
krb.EncTicketPart = new asn1.SEQUENCE(
    [{id: 'flags', type: krb.TicketFlags.tagged(asn1.tag(0))},
     {id: 'key', type: krb.EncryptionKey.tagged(asn1.tag(1))},
     {id: 'crealm', type: krb.Realm.tagged(asn1.tag(2))},
     {id: 'cname', type: krb.PrincipalName.tagged(asn1.tag(3))},
     {id: 'transited', type: krb.TransitedEncoding.tagged(asn1.tag(4))},
     {id: 'authtime', type: krb.KerberosTime.tagged(asn1.tag(5))},
     {id: 'starttime', type: krb.KerberosTime.tagged(asn1.tag(6)),
      optional: true},
     {id: 'endtime', type: krb.KerberosTime.tagged(asn1.tag(7))},
     {id: 'renewTill', type: krb.KerberosTime.tagged(asn1.tag(8)),
      optional: true},
     {id: 'caddr', type: krb.HostAddresses.tagged(asn1.tag(9)),
      optional: true},
     {id: 'authorizationData', type: krb.AuthorizationData.tagged(asn1.tag(10)),
      optional: true}]
).tagged(asn1.tag(3, asn1.TAG_CONSTRUCTED, asn1.TAG_APPLICATION));

// 5.4.1.  KRB_KDC_REQ Definition
krb.KDCOptions = krb.KerberosFlags;
krb.KDC_REQ_BODY = new asn1.SEQUENCE(
    [{id: 'kdcOptions', type: krb.KDCOptions.tagged(asn1.tag(0))},
     {id: 'principalName', type: krb.PrincipalName.tagged(asn1.tag(1)),
      optional: true},
     {id: 'realm', type: krb.Realm.tagged(asn1.tag(2))},
     {id: 'sname', type: krb.PrincipalName.tagged(asn1.tag(3)),
      optional: true},
     {id: 'from', type: krb.KerberosTime.tagged(asn1.tag(4)),
      optional: true},
     {id: 'till', type: krb.KerberosTime.tagged(asn1.tag(5))},
     {id: 'rtime', type: krb.KerberosTime.tagged(asn1.tag(6)),
      optional: true},
     {id: 'nonce', type: krb.UInt32.tagged(asn1.tag(7))},
     {id: 'etype', type: new asn1.SEQUENCE_OF(krb.Int32).tagged(asn1.tag(8))},
     {id: 'addresses', type: krb.HostAddresses.tagged(asn1.tag(9)),
      optional: true},
     {id: 'encAuthorizationData', type: krb.EncryptedData.tagged(asn1.tag(10)),
      optional: true},
     {id: 'additionalTickets',
      type: new asn1.SEQUENCE_OF(krb.Ticket).tagged(asn1.tag(10)),
      optional: true}]);
krb.KDC_REQ = new asn1.SEQUENCE(
    [{id: 'pvno', type: asn1.INTEGER.valueConstrained(5).tagged(asn1.tag(1))},
     {id: 'msgType',
      type: asn1.INTEGER.valueConstrained(10, 12).tagged(asn1.tag(2))},
     {id: 'padata',
      type: new asn1.SEQUENCE_OF(krb.PA_DATA).tagged(asn1.tag(3)),
      optional: true},
     {id: 'reqBody', type: krb.KDC_REQ_BODY.tagged(asn1.tag(4))}]);
krb.AS_REQ = krb.KDC_REQ.tagged(asn1.tag(10, asn1.TAG_CONSTRUCTED,
                                         asn1.TAG_APPLICATION));
krb.TGS_REQ = krb.KDC_REQ.tagged(asn1.tag(12, asn1.TAG_CONSTRUCTED,
                                         asn1.TAG_APPLICATION));

// 5.4.2.  KRB_KDC_REP Definition
krb.KDC_REP = new asn1.SEQUENCE(
    [{id: 'pvno', type: asn1.INTEGER.valueConstrained(5).tagged(asn1.tag(0))},
     {id: 'msgType',
      type: asn1.INTEGER.valueConstrained(11, 13).tagged(asn1.tag(1))},
     {id: 'padata',
      type: new asn1.SEQUENCE_OF(krb.PA_DATA).tagged(asn1.tag(2)),
      optional: true},
     {id: 'crealm', type: krb.Realm.tagged(asn1.tag(3))},
     {id: 'cname', type: krb.PrincipalName.tagged(asn1.tag(4))},
     {id: 'ticket', type: krb.Ticket.tagged(asn1.tag(5))},
     {id: 'encPart', type: krb.EncryptedData.tagged(asn1.tag(6))}]);
krb.AS_REP = krb.KDC_REP.tagged(asn1.tag(11, asn1.TAG_CONSTRUCTED,
                                         asn1.TAG_APPLICATION));
krb.TGS_REP = krb.KDC_REP.tagged(asn1.tag(13, asn1.TAG_CONSTRUCTED,
                                          asn1.TAG_APPLICATION));
krb.LastReq = new asn1.SEQUENCE_OF(new asn1.SEQUENCE(
    [{id: 'lrType', type: krb.Int32.tagged(asn1.tag(0))},
     {id: 'lrValue', type: krb.KerberosTime.tagged(asn1.tag(1))}]));
krb.EncKDCRepPart = new asn1.SEQUENCE(
    [{id: 'key', type: krb.EncryptionKey.tagged(asn1.tag(0))},
     {id: 'lastReq', type: krb.LastReq.tagged(asn1.tag(1))},
     {id: 'nonce', type: krb.UInt32.tagged(asn1.tag(2))},
     {id: 'keyExpiration', type: krb.KerberosTime.tagged(asn1.tag(3)),
      optional: true},
     {id: 'flags', type: krb.TicketFlags.tagged(asn1.tag(4))},
     {id: 'authtime', type: krb.KerberosTime.tagged(asn1.tag(5))},
     {id: 'starttime', type: krb.KerberosTime.tagged(asn1.tag(6)),
      optional: true},
     {id: 'endtime', type: krb.KerberosTime.tagged(asn1.tag(7))},
     {id: 'renewTill', type: krb.KerberosTime.tagged(asn1.tag(8)),
      optional: true},
     {id: 'srealm', type: krb.Realm.tagged(asn1.tag(9))},
     {id: 'sname', type: krb.PrincipalName.tagged(asn1.tag(10))},
     {id: 'caddr', type: krb.HostAddresses.tagged(asn1.tag(11)),
      optional: true}]);
krb.EncASRepPart = krb.EncKDCRepPart.tagged(asn1.tag(25, asn1.TAG_CONSTRUCTED,
                                                     asn1.TAG_APPLICATION));
krb.EncTGSRepPart = krb.EncKDCRepPart.tagged(asn1.tag(26, asn1.TAG_CONSTRUCTED,
                                                      asn1.TAG_APPLICATION));

// TODO: 5.5.1.  KRB_AP_REQ Definition

// TODO: 5.5.2.  KRB_AP_REP Definition

// TODO: 5.6.1.  KRB_SAFE Definition

// TODO: 5.7.1.  KRB_PRIV Definition

// TODO: 5.8.1.  KRB_CRED Definition

// TODO: 5.9.1.  KRB_ERROR Definition<|endoftext|>


<commit_before>"use strict";

window.modal = null;
window.ajax  = null;

Ajax = function () {
};

Ajax.default = {
    url                    : null,
    data                   : undefined,
    openModalOnError       : true,
    errorModalDialogContent: $('
')
        .append($('
')
            .append($('<button type="button" class="close" data-dismiss="modal"/>')
                .append($('').html('×'))
                .append($('').html('Close')))
            .append($('
')
                .append($(''))
                .append(' Error occurred')))
        .append($('
')
            .append($('
')
                .html('Error occurred during request. Please contact to page maintainer.')))
        .html()
};

/**
 * @param {String} url
 * @param {object} options
 * @returns {*}
 */
Ajax.prototype.ajax = function (url, options) {
    var jqXHR;

    options = $.extend({}, Ajax.default, options);

    jqXHR = $.ajax(url, options);
    this.registerErrorHandler(jqXHR, options);

    return jqXHR;
};

Ajax.prototype.registerErrorHandler = function (jqXHR, options) {
    jqXHR.fail(function (jqXHR, textStatus, errorThrown) {
        if (options.openModalOnError) {
            modal.open(options.errorModalDialogContent);
        }
        try {
            console.log(errorThrown, $.parseJSON(jqXHR.responseText));
        } catch (e) {
            console.log(errorThrown, {responseText: jqXHR.responseText});
        }
    });
};

Modal = function () {
    this._modal   = $('#modal');
    this._content = this._modal.find('.modal-content');
    this._dialog  = this._modal.find('.modal-dialog');
};

Modal.default = {
    open    : {
        content: null,
        size   : null
    },
    ajaxOpen: {
        ajax               : {},
        loadingModalContent: $('
')
            .append($('
')
                .append($('
')
                    .append($(''))))
            .html()
    }
};

Modal.prototype.ajax = function (url, options) {
    var self, jqXHR;

    self    = this;
    options = $.extend({}, Modal.default.ajaxOpen, options);

//    self.open(options.loadingModalContent, {
//        size: 'sm'
//    });

    jqXHR = ajax.ajax(url, options.ajax);

    jqXHR.done(function (data) {
        self.open(data);
    });
};

Modal.prototype.open = function (content, options) {
    options = $.extend({}, Modal.default.open, options);

    this._dialog.removeClass('modal-sm');
    if (options.size === 'lg') {
        this._dialog.addClass('modal-lg');
    } else if (options.size !== 'sm') {
        this._dialog.removeClass('modal-sm');
    }
    this._content.html(content);
    this._modal.modal({
        backdrop: 'static',
        keyboard: false
    });
};

(function ($) {
    'use strict';

    var temp;

    if ($.fn.tooltip) {
        temp = {
            container: 'body',
            selector : '[rel=tooltip]'
        };
        $(document).tooltip(temp);
    }

    if ($.fn.popover) {
        temp = {
            html     : true,
            container: 'body',
            selector : '[rel=popover]'
        };
        $(document).popover(temp);
    }

    $('body')
        .on('click', '[class^=js-btn-]', function (e) {
            e.preventDefault();
            e.returnValue = false;
        })
    ;

    $('#modal')
        .on('reload.bs.modal', function (e) {
            $(this).find('select.multiple').multiselect();
        })
        .on('loaded.bs.modal', function (e) {
            $(this).find('select.multiple').multiselect();
        })
        .on('hidden.bs.modal', function (e) {
            $(this).removeData('bs.modal');
            $(this).find('.modal-content').html('');
            $(this).find('.modal-dialog').removeClass('modal-sm');
            $(this).find('.modal-dialog').removeClass('modal-lg');
        })
        .on('keydown', 'input[data-index]', function (e) {
            if (e.which == 13) {
                var index = parseFloat($(e.target).attr('data-index'));

                $('#modal').find('[data-index="' + (index + 1).toString() + '"]')
                    .focus()
                    .click();

                e.preventDefault();
                return false;
            }
        })
    ;

    if ($.fn.multiselect) {
        $('select.multiple').multiselect();
    }

    $(document).ready(function () {
        var pageHeaderTopOffset;

        /** @type {Ajax} */
        window.ajax = new Ajax();
        /** @type {Modal} */
        window.modal = new Modal();

        if ($.fn.scrollspy) {
            pageHeaderTopOffset = $('.page-header').outerHeight(true) + $('.wiki-page-header').outerHeight(true);

            $('body').scrollspy({
                target: '.wiki-navbar-toc',
                offset: pageHeaderTopOffset
            });
        }

        if ($.fn.affix) {
            $('.wiki-page-toc').affix({
                offset: {
                    top   : function () {
                        return (this.top = $('.wiki-page-toc').offset().top);
                    },
                    bottom: function () {
                        return (this.bottom = $('.footer').outerHeight(true));
                    }
                }
            });
        }
    });

}(jQuery));

<commit_msg>Fixed modal dialog size not applied when opened as ajax request<commit_after>"use strict";

window.modal = null;
window.ajax  = null;

Ajax = function () {
};

Ajax.default = {
    url                    : null,
    data                   : undefined,
    openModalOnError       : true,
    errorModalDialogContent: $('
')
        .append($('
')
            .append($('<button type="button" class="close" data-dismiss="modal"/>')
                .append($('').html('×'))
                .append($('').html('Close')))
            .append($('
')
                .append($(''))
                .append(' Error occurred')))
        .append($('
')
            .append($('
')
                .html('Error occurred during request. Please contact to page maintainer.')))
        .html()
};

/**
 * @param {String} url
 * @param {object} options
 * @returns {*}
 */
Ajax.prototype.ajax = function (url, options) {
    var jqXHR;

    options = $.extend({}, Ajax.default, options);

    jqXHR = $.ajax(url, options);
    this.registerErrorHandler(jqXHR, options);

    return jqXHR;
};

Ajax.prototype.registerErrorHandler = function (jqXHR, options) {
    jqXHR.fail(function (jqXHR, textStatus, errorThrown) {
        if (options.openModalOnError) {
            modal.open(options.errorModalDialogContent);
        }
        try {
            console.log(errorThrown, $.parseJSON(jqXHR.responseText));
        } catch (e) {
            console.log(errorThrown, {responseText: jqXHR.responseText});
        }
    });
};

Modal = function () {
    this._modal   = $('#modal');
    this._content = this._modal.find('.modal-content');
    this._dialog  = this._modal.find('.modal-dialog');
};

Modal.default = {
    open    : {
        content: null,
        size   : null
    },
    ajaxOpen: {
        ajax               : {},
        loadingModalContent: $('
')
            .append($('
')
                .append($('
')
                    .append($(''))))
            .html()
    }
};

Modal.prototype.ajax = function (url, options) {
    var self, jqXHR;

    self    = this;
    options = $.extend({}, Modal.default.ajaxOpen, options);

//    self.open(options.loadingModalContent, {
//        size: 'sm'
//    });

    jqXHR = ajax.ajax(url, options.ajax);

    jqXHR.done(function (data) {
        self.open(data, options);
    });
};

Modal.prototype.open = function (content, options) {
    options = $.extend({}, Modal.default.open, options);

    this._dialog.removeClass('modal-sm');
    if (options.size === 'lg') {
        this._dialog.addClass('modal-lg');
    } else if (options.size !== 'sm') {
        this._dialog.removeClass('modal-sm');
    }
    this._content.html(content);
    this._modal.modal({
        backdrop: 'static',
        keyboard: false
    });
};

(function ($) {
    'use strict';

    var temp;

    if ($.fn.tooltip) {
        temp = {
            container: 'body',
            selector : '[rel=tooltip]'
        };
        $(document).tooltip(temp);
    }

    if ($.fn.popover) {
        temp = {
            html     : true,
            container: 'body',
            selector : '[rel=popover]'
        };
        $(document).popover(temp);
    }

    $('body')
        .on('click', '[class^=js-btn-]', function (e) {
            e.preventDefault();
            e.returnValue = false;
        })
    ;

    $('#modal')
        .on('reload.bs.modal', function (e) {
            $(this).find('select.multiple').multiselect();
        })
        .on('loaded.bs.modal', function (e) {
            $(this).find('select.multiple').multiselect();
        })
        .on('hidden.bs.modal', function (e) {
            $(this).removeData('bs.modal');
            $(this).find('.modal-content').html('');
            $(this).find('.modal-dialog').removeClass('modal-sm');
            $(this).find('.modal-dialog').removeClass('modal-lg');
        })
        .on('keydown', 'input[data-index]', function (e) {
            if (e.which == 13) {
                var index = parseFloat($(e.target).attr('data-index'));

                $('#modal').find('[data-index="' + (index + 1).toString() + '"]')
                    .focus()
                    .click();

                e.preventDefault();
                return false;
            }
        })
    ;

    if ($.fn.multiselect) {
        $('select.multiple').multiselect();
    }

    $(document).ready(function () {
        var pageHeaderTopOffset;

        /** @type {Ajax} */
        window.ajax = new Ajax();
        /** @type {Modal} */
        window.modal = new Modal();

        if ($.fn.scrollspy) {
            pageHeaderTopOffset = $('.page-header').outerHeight(true) + $('.wiki-page-header').outerHeight(true);

            $('body').scrollspy({
                target: '.wiki-navbar-toc',
                offset: pageHeaderTopOffset
            });
        }

        if ($.fn.affix) {
            $('.wiki-page-toc').affix({
                offset: {
                    top   : function () {
                        return (this.top = $('.wiki-page-toc').offset().top);
                    },
                    bottom: function () {
                        return (this.bottom = $('.footer').outerHeight(true));
                    }
                }
            });
        }
    });

}(jQuery));

<|endoftext|>


<commit_before>
var RG = require('./rg.js');

RG.Object = require('./object.js');
RG.Component = require('./component.js');
RG.Brain = require('./brain.js');
RG.Inv = require('./inv.js');

RG.Actor = {};

/* Object representing a game actor who takes actions.  */
RG.Actor.Rogue = function(name) { // {{{2
    RG.Object.Locatable.call(this);
    RG.Entity.call(this);
    this.setPropType('actors');

    // Member vars
    this._brain = new RG.Brain.Rogue(this);
    this._brain.getMemory().addEnemyType('player');

    let _name = name;
    this._isPlayer = false;
    let _fovRange = RG.FOV_RANGE;

    const _invEq = new RG.Inv.Inventory(this);
    const _maxWeight = 10.0;

    // Components for this entity
    this.add('Action', new RG.Component.Action());
    this.add('Experience', new RG.Component.Experience());
    this.add('Combat', new RG.Component.Combat());
    this.add('Stats', new RG.Component.Stats());
    this.add('Health', new RG.Component.Health(50));

    this.setName = function(name) {_name = name;};
    this.getName = function() {return _name;};

    /* Returns carrying capacity of the actor.*/
    this.getMaxWeight = function() {
        var statStr = this.get('Stats').getStrength();
        var eqStr = _invEq.getEquipment().getStrength();
        return 2 * statStr + 2 * eqStr + _maxWeight;
    };

    /* Returns true if actor is a player.*/
    this.isPlayer = function() {return this._isPlayer;};

    this.getFOVRange = function() { return _fovRange;};
    this.setFOVRange = function(range) {_fovRange = range;};

    //---------------------------------
    // Brain-relatd methods
    //---------------------------------

    this.addEnemy = function(actor) {this._brain.addEnemy(actor);};

    this.isEnemy = function(actor) {
        return this._brain.getMemory().isEnemy(actor);
    };

    this.getBrain = function() {return this._brain;};

    this.setBrain = function(brain) {
        this._brain = brain;
        this._brain.setActor(this);
    };

    //---------------------------------
    // Equipment related methods
    //---------------------------------

    this.getInvEq = function() { return _invEq; };

    /* Returns weapon that is wielded by the actor.*/
    this.getWeapon = function() {return _invEq.getWeapon();};

    /* Returns missile equipped by the player.*/
    this.getMissile = function() {
        return _invEq.getEquipment().getItem('missile');
    };

    this.getEquipAttack = function() {
        return _invEq.getEquipment().getAttack();
    };

    this.getEquipDefense = function() {
        return _invEq.getEquipment().getDefense();
    };

    this.getEquipProtection = function() {
        return _invEq.getEquipment().getProtection();
    };

};
RG.extend2(RG.Actor.Rogue, RG.Object.Locatable);
RG.extend2(RG.Actor.Rogue, RG.Entity);

/* Marks actor as player. Cannot unset player.*/
RG.Actor.Rogue.prototype.setIsPlayer = function(isPlayer) {
    if (isPlayer) {
        this._isPlayer = isPlayer;
        this._brain = new RG.Brain.Player(this);
        this.setType('player');
        this.add('StatsMods', new RG.Component.StatsMods());
        this.add('CombatMods', new RG.Component.CombatMods());
    }
    else {
        RG.err('Actor.Rogue', 'setIsPlayer',
            'Actor cannot be changed from player to mob.');
    }
};

/* Returns the next action for this actor.*/
RG.Actor.Rogue.prototype.nextAction = function(obj) {
    // Use actor brain to determine the action
    var cb = this._brain.decideNextAction(obj);
    var action = null;

    if (cb !== null) {
        const speed = this.getSpeed();
        const duration = parseInt(RG.BASE_SPEED / speed * RG.ACTION_DUR, 10);
        action = new RG.Time.RogueAction(duration, cb, {});
    }
    else {
        action = new RG.Time.RogueAction(0, function() {}, {});
    }

    if (this._brain.hasOwnProperty('energy')) {
        action.energy = this._brain.energy;
    }
    action.actor = this;
    return action;
};

/* Returns the cell where this actor is located at.*/
RG.Actor.Rogue.prototype.getCell = function() {
    var x = this.getX();
    var y = this.getY();
    return this.getLevel().getMap().getCell(x, y);
};

RG.Actor.Rogue.prototype.toJSON = function() {
    var obj = {
        name: this.getName(),
        type: this.getType(),
        components: {
            Combat: this.get('Combat').toJSON(),
            Experience: this.get('Experience').toJSON(),
            Health: this.get('Health').toJSON(),
            Stats: this.get('Stats').toJSON()
        },
        inventory: this.getInvEq().getInventory().toJSON(),
        equipment: this.getInvEq().getEquipment().toJSON()
    };

    if (this.has('Hunger')) {
        obj.components.Hunger = this.get('Hunger').toJSON();
    }

    return obj;
};

//---------------------------------
// Combat-related methods
//---------------------------------

RG.Actor.Rogue.prototype.getAttack = function() {
    var attack = this.get('Combat').getAttack();
    attack += this.getEquipAttack();

    if (this.has('CombatMods')) {
        attack += this.get('CombatMods').getAttack();
    }

    attack += Math.floor(this.getAccuracy() / 2);
    return attack;
};

RG.Actor.Rogue.prototype.getDefense = function() {
    var defense = this.get('Combat').getDefense();
    defense += this.getEquipDefense();
    if (this.has('CombatMods')) {
        defense += this.get('CombatMods').getDefense();
    }
    defense += Math.floor(this.getAgility() / 2);
    return defense;
};

RG.Actor.Rogue.prototype.getProtection = function() {
    var protection = this.get('Combat').getProtection();
    protection += this.getEquipProtection();
    if (this.has('CombatMods')) {
        protection += this.get('CombatMods').getProtection();
    }
    return protection;
};

RG.Actor.Rogue.prototype.getDamage = function() {
    var damage = this.get('Combat').getDamage();
    var strength = this.getStrength();
    strength += this.getInvEq().getEquipment().getStrength();
    damage += RG.strengthToDamage(strength);
    if (this.has('CombatMods')) {damage += this.get('CombatMods').getDamage();}
    return damage;

};

//-------------------------------------------------------------
// Stats-related methods (these take eq and boosts into account
//-------------------------------------------------------------

RG.Actor.Rogue.prototype.getAccuracy = function() {
    var acc = this.get('Stats').getAccuracy();
    acc += this.getInvEq().getEquipment().getAccuracy();
    if (this.has('StatsMods')) {acc += this.get('StatsMods').getAccuracy();}
    return acc;
};

RG.Actor.Rogue.prototype.getAgility = function() {
    var agi = this.get('Stats').getAgility();
    agi += this.getInvEq().getEquipment().getAgility();
    if (this.has('StatsMods')) {agi += this.get('StatsMods').getAgility();}
    return agi;
};

RG.Actor.Rogue.prototype.getStrength = function() {
    var str = this.get('Stats').getStrength();
    str += this.getInvEq().getEquipment().getStrength();
    if (this.has('StatsMods')) {str += this.get('StatsMods').getStrength();}
    return str;
};

RG.Actor.Rogue.prototype.getWillpower = function() {
    var wil = this.get('Stats').getWillpower();
    wil += this.getInvEq().getEquipment().getWillpower();
    if (this.has('StatsMods')) {wil += this.get('StatsMods').getWillpower();}
    return wil;
};

RG.Actor.Rogue.prototype.getSpeed = function() {
    var speed = this.get('Stats').getSpeed();
    speed += this.getInvEq().getEquipment().getSpeed();
    if (this.has('StatsMods')) {speed += this.get('StatsMods').getSpeed();}
    return speed;

};

/* Spirit actors. They have Ethereal component and cannot be attacked, but they
 * can be captured by SpiritGem-objects.*/
RG.Actor.Spirit = function(name) {
    RG.Actor.Rogue.call(this, name);
    this.setType('spirit');

    this.add('Ethereal', new RG.Component.Ethereal());

    const spiritBrain = new RG.Brain.Spirit(this);
    this.setBrain(spiritBrain);

};
RG.extend2(RG.Actor.Spirit, RG.Actor.Rogue);

module.exports = RG.Actor;
<commit_msg>Changed _invEq -> this._invEq.<commit_after>
var RG = require('./rg.js');

RG.Object = require('./object.js');
RG.Component = require('./component.js');
RG.Brain = require('./brain.js');
RG.Inv = require('./inv.js');

RG.Actor = {};

/* Object representing a game actor who takes actions.  */
RG.Actor.Rogue = function(name) { // {{{2
    RG.Object.Locatable.call(this);
    RG.Entity.call(this);
    this.setPropType('actors');

    // Member vars
    this._brain = new RG.Brain.Rogue(this);
    this._brain.getMemory().addEnemyType('player');

    let _name = name;
    this._isPlayer = false;
    let _fovRange = RG.FOV_RANGE;

    this._invEq = new RG.Inv.Inventory(this);
    this._maxWeight = 10.0;

    // Components for this entity
    this.add('Action', new RG.Component.Action());
    this.add('Experience', new RG.Component.Experience());
    this.add('Combat', new RG.Component.Combat());
    this.add('Stats', new RG.Component.Stats());
    this.add('Health', new RG.Component.Health(50));

    this.setName = function(name) {_name = name;};
    this.getName = function() {return _name;};

    /* Returns true if actor is a player.*/
    this.isPlayer = function() {return this._isPlayer;};

    this.getFOVRange = function() { return _fovRange;};
    this.setFOVRange = function(range) {_fovRange = range;};

    //---------------------------------
    // Brain-relatd methods
    //---------------------------------

    this.addEnemy = function(actor) {this._brain.addEnemy(actor);};

    this.isEnemy = function(actor) {
        return this._brain.getMemory().isEnemy(actor);
    };

    this.getBrain = function() {return this._brain;};

    this.setBrain = function(brain) {
        this._brain = brain;
        this._brain.setActor(this);
    };

    //---------------------------------
    // Equipment related methods
    //---------------------------------

    this.getInvEq = function() { return this._invEq; };

    /* Returns weapon that is wielded by the actor.*/
    this.getWeapon = function() {return this._invEq.getWeapon();};

    /* Returns missile equipped by the player.*/
    this.getMissile = function() {
        return this._invEq.getEquipment().getItem('missile');
    };

    this.getEquipAttack = function() {
        return this._invEq.getEquipment().getAttack();
    };

    this.getEquipDefense = function() {
        return this._invEq.getEquipment().getDefense();
    };

    this.getEquipProtection = function() {
        return this._invEq.getEquipment().getProtection();
    };

};
RG.extend2(RG.Actor.Rogue, RG.Object.Locatable);
RG.extend2(RG.Actor.Rogue, RG.Entity);

/* Returns carrying capacity of the actor.*/
RG.Actor.Rogue.prototype.getMaxWeight = function() {
    var statStr = this.get('Stats').getStrength();
    var eqStr = this._invEq.getEquipment().getStrength();
    return 2 * statStr + 2 * eqStr + this._maxWeight;
};

/* Marks actor as player. Cannot unset player.*/
RG.Actor.Rogue.prototype.setIsPlayer = function(isPlayer) {
    if (isPlayer) {
        this._isPlayer = isPlayer;
        this._brain = new RG.Brain.Player(this);
        this.setType('player');
        this.add('StatsMods', new RG.Component.StatsMods());
        this.add('CombatMods', new RG.Component.CombatMods());
    }
    else {
        RG.err('Actor.Rogue', 'setIsPlayer',
            'Actor cannot be changed from player to mob.');
    }
};

/* Returns the next action for this actor.*/
RG.Actor.Rogue.prototype.nextAction = function(obj) {
    // Use actor brain to determine the action
    var cb = this._brain.decideNextAction(obj);
    var action = null;

    if (cb !== null) {
        const speed = this.getSpeed();
        const duration = parseInt(RG.BASE_SPEED / speed * RG.ACTION_DUR, 10);
        action = new RG.Time.RogueAction(duration, cb, {});
    }
    else {
        action = new RG.Time.RogueAction(0, function() {}, {});
    }

    if (this._brain.hasOwnProperty('energy')) {
        action.energy = this._brain.energy;
    }
    action.actor = this;
    return action;
};

/* Returns the cell where this actor is located at.*/
RG.Actor.Rogue.prototype.getCell = function() {
    var x = this.getX();
    var y = this.getY();
    return this.getLevel().getMap().getCell(x, y);
};

RG.Actor.Rogue.prototype.toJSON = function() {
    var obj = {
        name: this.getName(),
        type: this.getType(),
        components: {
            Combat: this.get('Combat').toJSON(),
            Experience: this.get('Experience').toJSON(),
            Health: this.get('Health').toJSON(),
            Stats: this.get('Stats').toJSON()
        },
        inventory: this.getInvEq().getInventory().toJSON(),
        equipment: this.getInvEq().getEquipment().toJSON()
    };

    if (this.has('Hunger')) {
        obj.components.Hunger = this.get('Hunger').toJSON();
    }

    return obj;
};

//---------------------------------
// Combat-related methods
//---------------------------------

RG.Actor.Rogue.prototype.getAttack = function() {
    var attack = this.get('Combat').getAttack();
    attack += this.getEquipAttack();

    if (this.has('CombatMods')) {
        attack += this.get('CombatMods').getAttack();
    }

    attack += Math.floor(this.getAccuracy() / 2);
    return attack;
};

RG.Actor.Rogue.prototype.getDefense = function() {
    var defense = this.get('Combat').getDefense();
    defense += this.getEquipDefense();
    if (this.has('CombatMods')) {
        defense += this.get('CombatMods').getDefense();
    }
    defense += Math.floor(this.getAgility() / 2);
    return defense;
};

RG.Actor.Rogue.prototype.getProtection = function() {
    var protection = this.get('Combat').getProtection();
    protection += this.getEquipProtection();
    if (this.has('CombatMods')) {
        protection += this.get('CombatMods').getProtection();
    }
    return protection;
};

RG.Actor.Rogue.prototype.getDamage = function() {
    var damage = this.get('Combat').getDamage();
    var strength = this.getStrength();
    strength += this.getInvEq().getEquipment().getStrength();
    damage += RG.strengthToDamage(strength);
    if (this.has('CombatMods')) {damage += this.get('CombatMods').getDamage();}
    return damage;

};

//-------------------------------------------------------------
// Stats-related methods (these take eq and boosts into account
//-------------------------------------------------------------

RG.Actor.Rogue.prototype.getAccuracy = function() {
    var acc = this.get('Stats').getAccuracy();
    acc += this.getInvEq().getEquipment().getAccuracy();
    if (this.has('StatsMods')) {acc += this.get('StatsMods').getAccuracy();}
    return acc;
};

RG.Actor.Rogue.prototype.getAgility = function() {
    var agi = this.get('Stats').getAgility();
    agi += this.getInvEq().getEquipment().getAgility();
    if (this.has('StatsMods')) {agi += this.get('StatsMods').getAgility();}
    return agi;
};

RG.Actor.Rogue.prototype.getStrength = function() {
    var str = this.get('Stats').getStrength();
    str += this.getInvEq().getEquipment().getStrength();
    if (this.has('StatsMods')) {str += this.get('StatsMods').getStrength();}
    return str;
};

RG.Actor.Rogue.prototype.getWillpower = function() {
    var wil = this.get('Stats').getWillpower();
    wil += this.getInvEq().getEquipment().getWillpower();
    if (this.has('StatsMods')) {wil += this.get('StatsMods').getWillpower();}
    return wil;
};

RG.Actor.Rogue.prototype.getSpeed = function() {
    var speed = this.get('Stats').getSpeed();
    speed += this.getInvEq().getEquipment().getSpeed();
    if (this.has('StatsMods')) {speed += this.get('StatsMods').getSpeed();}
    return speed;

};

/* Spirit actors. They have Ethereal component and cannot be attacked, but they
 * can be captured by SpiritGem-objects.*/
RG.Actor.Spirit = function(name) {
    RG.Actor.Rogue.call(this, name);
    this.setType('spirit');

    this.add('Ethereal', new RG.Component.Ethereal());

    const spiritBrain = new RG.Brain.Spirit(this);
    this.setBrain(spiritBrain);

};
RG.extend2(RG.Actor.Spirit, RG.Actor.Rogue);

module.exports = RG.Actor;
<|endoftext|>