<commit_before>module.exports = normalize

const env = require('../env')
const headers = require('../headers')
const setIfExists = require('../set-if-exists')
const temporaryRepository = require('../temporary-repository')
const toEntityName = require('../to-entity-name')

function normalize (fixture) {
  // fixture.rawHeaders is an array in the form of ['key1', 'value1', 'key2', 'value2']
  // But the order of these can change, e.g. between local tests and CI on Travis.
  // That’s why we turn them into an object before storing the fixtures and turn
  // them back into an array before loading
  fixture.headers = headers.toObject(fixture.rawHeaders)
  delete fixture.rawHeaders

  // rename temporary repositories
  // e.g. tmp-scenario-bar-20170924033013835 => bar
  if (temporaryRepository.regex.test(fixture.path)) {
    fixture.path = fixture.path.replace(temporaryRepository.regex, '$1')
  }
  if (fixture.headers.location && temporaryRepository.regex.test(fixture.headers.location)) {
    fixture.headers.location = fixture.headers.location.replace(temporaryRepository.regex, '$1')
  }

  // set all IDs in paths to 1
  fixture.path = fixture.path.replace(/\d+$/, 1)
  if (fixture.headers.location) {
    fixture.headers.location = fixture.headers.location.replace(/\d+$/, 1)
  }

  // set all dates to Universe 2017 Keynote time
  setIfExists(fixture.headers, 'date', 'Tue, 10 Oct 2017 16:00:00 GMT')
  setIfExists(fixture.headers, 'last-modified', 'Tue, 10 Oct 2017 16:00:00 GMT')
  setIfExists(fixture.headers, 'x-ratelimit-reset', '1507651200000')

  // Set remaining rate limit to 59 for unauthenticated accounts and
  // to 4999 to authenticated accounts
  const rateLimitRemaining = parseInt(fixture.headers['x-ratelimit-limit'], 10)
  setIfExists(fixture.headers, 'x-ratelimit-remaining', String(rateLimitRemaining - 1))

  // zerofy random stuff
  setIfExists(fixture.headers, 'etag', '"00000000000000000000000000000000"')
  setIfExists(fixture.headers, 'x-runtime-rack', '0.000000')
  setIfExists(fixture.headers, 'x-github-request-id', '0000:00000:0000000:0000000:00000000')

  // zerofy auth token (if present)
  if (fixture.reqheaders.authorization) {
    fixture.reqheaders.authorization = fixture.reqheaders.authorization.replace(/^token \w{40}$/, 'token 0000000000000000000000000000000000000000')
  } else {
    // otherwise add authorization to "badheaders" to help with matching the
    // right fixture to the right request
    fixture.badheaders = ['authorization']
  }

  // workaround for https://github.com/gr2m/octokit-fixtures/issues/3
  if (env.FIXTURES_PROXY) {
    fixture.scope = 'https://api.github.com:443'
    fixture.reqheaders.host = 'api.github.com'
    delete fixture.headers['x-powered-by']
  }

  // leave out headers that tend to change on different environments
  delete fixture.headers['accept-ranges']
  delete fixture.headers.region
  delete fixture.headers.server
  delete fixture.headers.vary

  // The GitHub API has several endpoints that require a PUT or a PATCH verb
  // with an empty body. In that case it’s unclear what content-type to set,
  // or if a content-type header is to be set at all. So we remove it from our
  // fixtures in that case but set content-length to 0 as required via:
  // https://developer.github.com/v3/#http-verbs
  if ((fixture.method === 'put' || fixture.method === 'patch') && !fixture.body) {
    delete fixture.reqheaders['content-type']
    fixture.reqheaders['content-length'] = 0
  }

  const responses = Array.isArray(fixture.response) ? fixture.response : [fixture.response]
  responses.forEach(response => {
    const entityName = toEntityName(response)
    if (entityName) {
      require(`./${entityName}`)(response)
    }
  })

  // remove headers added by proxy
  // see https://github.com/gr2m/octokit-fixtures/pull/20#issuecomment-331558385
  delete fixture.headers['x-now-region']

  // update content length
  fixture.headers['content-length'] = String(JSON.stringify(fixture.response).length)

  return fixture
}
<commit_msg>fix(normalization): `application/json;charset=utf-8` -> `application/json; charset=utf-8`<commit_after>module.exports = normalize

const env = require('../env')
const headers = require('../headers')
const setIfExists = require('../set-if-exists')
const temporaryRepository = require('../temporary-repository')
const toEntityName = require('../to-entity-name')

function normalize (fixture) {
  // fixture.rawHeaders is an array in the form of ['key1', 'value1', 'key2', 'value2']
  // But the order of these can change, e.g. between local tests and CI on Travis.
  // That’s why we turn them into an object before storing the fixtures and turn
  // them back into an array before loading
  fixture.headers = headers.toObject(fixture.rawHeaders)
  delete fixture.rawHeaders

  // rename temporary repositories
  // e.g. tmp-scenario-bar-20170924033013835 => bar
  if (temporaryRepository.regex.test(fixture.path)) {
    fixture.path = fixture.path.replace(temporaryRepository.regex, '$1')
  }
  if (fixture.headers.location && temporaryRepository.regex.test(fixture.headers.location)) {
    fixture.headers.location = fixture.headers.location.replace(temporaryRepository.regex, '$1')
  }

  // set all IDs in paths to 1
  fixture.path = fixture.path.replace(/\d+$/, 1)
  if (fixture.headers.location) {
    fixture.headers.location = fixture.headers.location.replace(/\d+$/, 1)
  }

  // set all dates to Universe 2017 Keynote time
  setIfExists(fixture.headers, 'date', 'Tue, 10 Oct 2017 16:00:00 GMT')
  setIfExists(fixture.headers, 'last-modified', 'Tue, 10 Oct 2017 16:00:00 GMT')
  setIfExists(fixture.headers, 'x-ratelimit-reset', '1507651200000')

  // Set remaining rate limit to 59 for unauthenticated accounts and
  // to 4999 to authenticated accounts
  const rateLimitRemaining = parseInt(fixture.headers['x-ratelimit-limit'], 10)
  setIfExists(fixture.headers, 'x-ratelimit-remaining', String(rateLimitRemaining - 1))

  // zerofy random stuff
  setIfExists(fixture.headers, 'etag', '"00000000000000000000000000000000"')
  setIfExists(fixture.headers, 'x-runtime-rack', '0.000000')
  setIfExists(fixture.headers, 'x-github-request-id', '0000:00000:0000000:0000000:00000000')

  // zerofy auth token (if present)
  if (fixture.reqheaders.authorization) {
    fixture.reqheaders.authorization = fixture.reqheaders.authorization.replace(/^token \w{40}$/, 'token 0000000000000000000000000000000000000000')
  } else {
    // otherwise add authorization to "badheaders" to help with matching the
    // right fixture to the right request
    fixture.badheaders = ['authorization']
  }

  // workaround for https://github.com/gr2m/octokit-fixtures/issues/3
  if (env.FIXTURES_PROXY) {
    fixture.scope = 'https://api.github.com:443'
    fixture.reqheaders.host = 'api.github.com'
    delete fixture.headers['x-powered-by']
  }

  // leave out headers that tend to change on different environments
  delete fixture.headers['accept-ranges']
  delete fixture.headers.region
  delete fixture.headers.server
  delete fixture.headers.vary

  // The GitHub API has several endpoints that require a PUT or a PATCH verb
  // with an empty body. In that case it’s unclear what content-type to set,
  // or if a content-type header is to be set at all. So we remove it from our
  // fixtures in that case but set content-length to 0 as required via:
  // https://developer.github.com/v3/#http-verbs
  if ((fixture.method === 'put' || fixture.method === 'patch') && !fixture.body) {
    delete fixture.reqheaders['content-type']
    fixture.reqheaders['content-length'] = 0
  }

  // normalize content-type value
  if (fixture.reqheaders['content-type']) {
    fixture.reqheaders['content-type'] = fixture.reqheaders['content-type'].replace(';charset=utf-8', '; charset=utf-8')
  }

  const responses = Array.isArray(fixture.response) ? fixture.response : [fixture.response]
  responses.forEach(response => {
    const entityName = toEntityName(response)
    if (entityName) {
      require(`./${entityName}`)(response)
    }
  })

  // remove headers added by proxy
  // see https://github.com/gr2m/octokit-fixtures/pull/20#issuecomment-331558385
  delete fixture.headers['x-now-region']

  // update content length
  fixture.headers['content-length'] = String(JSON.stringify(fixture.response).length)

  return fixture
}
<|endoftext|>


<commit_before>const {Disposable, CompositeDisposable} = require("atom")
const Base = require("./base")
let OperationAbortedError, Select, MoveToRelativeLine

// opration life in operationStack
// 1. run
//    instantiated by new.
//    compliment implicit Operator.Select operator if necessary.
//    push operation to stack.
// 2. process
//    reduce stack by, popping top of stack then set it as target of new top.
//    check if remaining top of stack is executable by calling isComplete()
//    if executable, then pop stack then execute(poppedOperation)
//    if not executable, enter "operator-pending-mode"
module.exports = class OperationStack {
  get mode() {
    return this.modeManager.mode
  }
  get submode() {
    return this.modeManager.submode
  }

  constructor(vimState) {
    this.vimState = vimState
    this.editor = vimState.editor
    this.editorElement = vimState.editorElement
    this.modeManager = vimState.modeManager
    this.swrap = this.vimState.swrap // intentionally access prop to populate.

    this.vimState.onDidDestroy(() => this.destroy())

    this.reset()
  }

  // Return handler
  subscribe(handler) {
    this.operationSubscriptions.add(handler)
    return handler // DONT REMOVE
  }

  getLastCommandName() {
    return this.lastCommandName
  }

  reset() {
    this.resetCount()
    this.stack = []
    this.running = false

    // this has to be BEFORE this.operationSubscriptions.dispose()
    this.vimState.emitDidResetOperationStack()

    if (this.operationSubscriptions) this.operationSubscriptions.dispose()
    this.operationSubscriptions = new CompositeDisposable()
  }

  destroy() {
    if (this.operationSubscriptions) this.operationSubscriptions.dispose()
    this.stack = this.operationSubscriptions = null
  }

  peekTop() {
    return this.stack[this.stack.length - 1]
  }

  isEmpty() {
    return this.stack.length === 0
  }

  newMoveToRelativeLine() {
    if (!MoveToRelativeLine) MoveToRelativeLine = Base.getClass("MoveToRelativeLine")
    return new MoveToRelativeLine(this.vimState)
  }

  newSelectWithTarget(target) {
    if (!Select) Select = Base.getClass("Select")
    return new Select(this.vimState).setTarget(target)
  }

  // Main
  // -------------------------
  run(klass, properties) {
    this.running = true

    if (this.mode === "visual") {
      for (const $selection of this.swrap.getSelections(this.editor)) {
        if (!$selection.hasProperties()) $selection.saveProperties()
      }
    }

    try {
      if (this.isEmpty()) this.vimState.init()
      const type = typeof klass

      let operation
      if (type === "object") {
        // . repeat case we can execute as-it-is.
        operation = klass
      } else {
        if (type === "string") klass = Base.getClass(klass)

        const stackTop = this.peekTop()
        if (stackTop && stackTop.constructor === klass) {
          // Replace operator when identical one repeated, e.g. `dd`, `cc`, `gUgU`
          operation = this.newMoveToRelativeLine()
        } else {
          operation = new klass(this.vimState, properties)
        }
      }

      if (this.isEmpty()) {
        if ((this.mode === "visual" && operation.isMotion()) || operation.isTextObject()) {
          operation = this.newSelectWithTarget(operation)
        }
        this.stack.push(operation)
        this.process()
      } else if (this.peekTop().isOperator() && (operation.isMotion() || operation.isTextObject())) {
        this.stack.push(operation)
        this.process()
      } else {
        this.vimState.emitDidFailToPushToOperationStack()
        this.vimState.resetNormalMode()
      }
    } catch (error) {
      this.handleError(error)
    }
  }

  runRecorded() {
    if (!this.recordedOperation) return

    const operation = this.recordedOperation
    operation.repeated = true
    if (this.hasCount()) {
      const count = this.getCount()
      operation.count = count

      // Why gurad? some opeartor have no target like ctrl-a(increase).
      if (operation.target) operation.target.count = count
    }

    operation.subscribeResetOccurrencePatternIfNeeded()
    this.run(operation)
  }

  runRecordedMotion(key, {reverse} = {}) {
    const recoded = this.vimState.globalState.get(key)
    if (!recoded) return

    const operation = recoded.clone(this.vimState)
    operation.repeated = true
    operation.resetCount()
    if (reverse) operation.backwards = !operation.backwards
    this.run(operation)
  }

  runCurrentFind(options) {
    this.runRecordedMotion("currentFind", options)
  }

  runCurrentSearch(options) {
    this.runRecordedMotion("currentSearch", options)
  }

  handleError(error) {
    this.vimState.reset()
    if (!OperationAbortedError) OperationAbortedError = require("./errors")
    if (!(error instanceof OperationAbortedError)) throw error
  }

  isRunning() {
    return this.running
  }

  process() {
    if (this.stack.length === 2) {
      // [FIXME ideally]
      // If target is not complete, we postpone composing target with operator to keep situation simple.
      // So that we can assume when target is set to operator it's complete.
      // e.g. `y s t a'(surround for range from here to till a)
      if (!this.peekTop().isComplete()) return

      const operation = this.stack.pop()
      this.peekTop().setTarget(operation)
    }

    const top = this.peekTop()

    if (!top.isComplete()) {
      if (this.mode === "normal" && top.isOperator()) {
        this.modeManager.activate("operator-pending")
      }
      this.addOperatorSpecificPendingScope(top)
    } else {
      this.execute(this.stack.pop())
    }
  }

  addOperatorSpecificPendingScope(operation) {
    // Temporary set while command is running
    const commandName =
      typeof operation.constructor.getCommandNameWithoutPrefix === "function"
        ? operation.constructor.getCommandNameWithoutPrefix()
        : undefined
    if (commandName) {
      this.addToClassList(commandName + "-pending")
    }
  }

  execute(operation) {
    // Intentionally avoild wrapping by Promise.resolve() to make test easy.
    // Since almost all command don't return promise, finish synchronously.
    const execution = operation.execute()
    if (execution instanceof Promise) {
      execution.then(() => this.finish(operation)).catch(() => this.handleError())
    } else {
      this.finish(operation)
    }
  }

  cancel(operation) {
    if (!["visual", "insert"].includes(this.mode)) {
      this.vimState.resetNormalMode()
      this.vimState.restoreOriginalCursorPosition()
    }
    this.finish(operation)
  }

  finish(operation) {
    if (operation.recordable) this.recordedOperation = operation
    this.lastCommandName = operation.name

    this.vimState.emitDidFinishOperation()
    if (operation.isOperator()) operation.resetState()

    if (this.mode === "normal") {
      this.ensureAllSelectionsAreEmpty(operation)
      this.ensureAllCursorsAreNotAtEndOfLine()
    } else if (this.mode === "visual") {
      this.modeManager.updateNarrowedState()
      this.vimState.updatePreviousSelection()
    }

    this.vimState.cursorStyleManager.refresh()
    this.vimState.reset()
  }

  ensureAllSelectionsAreEmpty(operation) {
    // When @vimState.selectBlockwise() is called in non-visual-mode.
    // e.g. `.` repeat of operation targeted blockwise `CurrentSelection`.
    // We need to manually clear blockwiseSelection.
    // See #647
    this.vimState.clearBlockwiseSelections() // FIXME, should be removed
    if (this.vimState.haveSomeNonEmptySelection()) {
      if (this.vimState.getConfig("strictAssertion")) {
        const message = `Have some non-empty selection in normal-mode: ${operation.toString()}`
        this.vimState.utils.assertWithException(false, message)
      }
      this.vimState.clearSelections()
    }
  }

  ensureAllCursorsAreNotAtEndOfLine() {
    this.editor
      .getCursors()
      .filter(cursor => cursor.isAtEndOfLine())
      .map(cursor => this.vimState.utils.moveCursorLeft(cursor, {preserveGoalColumn: true}))
  }

  addToClassList(className) {
    this.editorElement.classList.add(className)
    this.subscribe(new Disposable(() => this.editorElement.classList.remove(className)))
  }

  // Count
  // -------------------------
  // keystroke `3d2w` delete 6(3*2) words.
  //  2nd number(2 in this case) is always enterd in operator-pending-mode.
  //  So count have two timing to be entered. that's why here we manage counter by mode.
  hasCount() {
    return this.count["normal"] != null || this.count["operator-pending"] != null
  }

  getCount() {
    if (this.hasCount()) {
      return (
        (this.count["normal"] != null ? this.count["normal"] : 1) *
        (this.count["operator-pending"] != null ? this.count["operator-pending"] : 1)
      )
    } else {
      return null
    }
  }

  setCount(number) {
    const mode = this.mode === "operator-pending" ? this.mode : "normal"
    if (this.count[mode] == null) this.count[mode] = 0
    this.count[mode] = this.count[mode] * 10 + number
    this.vimState.hover.set(this.buildCountString())
    this.editorElement.classList.toggle("with-count", true)
  }

  buildCountString() {
    return [this.count["normal"], this.count["operator-pending"]].filter(n => n != null).join("x")
  }

  resetCount() {
    this.count = {}
    this.editorElement.classList.remove("with-count")
  }
}
<commit_msg>improve explicitness<commit_after>const {Disposable, CompositeDisposable} = require("atom")
const Base = require("./base")
let OperationAbortedError, Select, MoveToRelativeLine

// opration life in operationStack
// 1. run
//    instantiated by new.
//    compliment implicit Operator.Select operator if necessary.
//    push operation to stack.
// 2. process
//    reduce stack by, popping top of stack then set it as target of new top.
//    check if remaining top of stack is executable by calling isComplete()
//    if executable, then pop stack then execute(poppedOperation)
//    if not executable, enter "operator-pending-mode"
module.exports = class OperationStack {
  get mode() {
    return this.modeManager.mode
  }
  get submode() {
    return this.modeManager.submode
  }

  constructor(vimState) {
    this.vimState = vimState
    this.editor = vimState.editor
    this.editorElement = vimState.editorElement
    this.modeManager = vimState.modeManager
    this.swrap = this.vimState.swrap // intentionally access prop to populate.

    this.vimState.onDidDestroy(() => this.destroy())

    this.reset()
  }

  // Return handler
  subscribe(handler) {
    this.operationSubscriptions.add(handler)
    return handler // DONT REMOVE
  }

  getLastCommandName() {
    return this.lastCommandName
  }

  reset() {
    this.resetCount()
    this.stack = []
    this.running = false

    // this has to be BEFORE this.operationSubscriptions.dispose()
    this.vimState.emitDidResetOperationStack()

    if (this.operationSubscriptions) this.operationSubscriptions.dispose()
    this.operationSubscriptions = new CompositeDisposable()
  }

  destroy() {
    if (this.operationSubscriptions) this.operationSubscriptions.dispose()
    this.stack = this.operationSubscriptions = null
  }

  peekTop() {
    return this.stack[this.stack.length - 1]
  }

  isEmpty() {
    return this.stack.length === 0
  }

  newMoveToRelativeLine() {
    if (!MoveToRelativeLine) MoveToRelativeLine = Base.getClass("MoveToRelativeLine")
    return new MoveToRelativeLine(this.vimState)
  }

  newSelectWithTarget(target) {
    if (!Select) Select = Base.getClass("Select")
    return new Select(this.vimState).setTarget(target)
  }

  // Main
  // -------------------------
  run(klass, properties) {
    this.running = true

    if (this.mode === "visual") {
      for (const $selection of this.swrap.getSelections(this.editor)) {
        if (!$selection.hasProperties()) $selection.saveProperties()
      }
    }

    try {
      if (this.isEmpty()) this.vimState.init()
      const type = typeof klass

      let operation
      if (type === "object") {
        // . repeat case we can execute as-it-is.
        operation = klass
      } else {
        if (type === "string") klass = Base.getClass(klass)

        const stackTop = this.peekTop()
        if (stackTop && stackTop.constructor === klass) {
          // Replace operator when identical one repeated, e.g. `dd`, `cc`, `gUgU`
          operation = this.newMoveToRelativeLine()
        } else {
          operation = new klass(this.vimState, properties)
        }
      }

      if (this.isEmpty()) {
        if ((this.mode === "visual" && operation.isMotion()) || operation.isTextObject()) {
          operation = this.newSelectWithTarget(operation)
        }
        this.stack.push(operation)
        this.process()
      } else if (this.peekTop().isOperator() && (operation.isMotion() || operation.isTextObject())) {
        this.stack.push(operation)
        this.process()
      } else {
        this.vimState.emitDidFailToPushToOperationStack()
        this.vimState.resetNormalMode()
      }
    } catch (error) {
      this.handleError(error)
    }
  }

  runRecorded() {
    if (!this.recordedOperation) return

    const operation = this.recordedOperation
    operation.repeated = true
    if (this.hasCount()) {
      const count = this.getCount()
      operation.count = count

      // Why gurad? some opeartor have no target like ctrl-a(increase).
      if (operation.target) operation.target.count = count
    }

    operation.subscribeResetOccurrencePatternIfNeeded()
    this.run(operation)
  }

  runRecordedMotion(key, {reverse} = {}) {
    const recoded = this.vimState.globalState.get(key)
    if (!recoded) return

    const operation = recoded.clone(this.vimState)
    operation.repeated = true
    operation.resetCount()
    if (reverse) operation.backwards = !operation.backwards
    this.run(operation)
  }

  runCurrentFind(options) {
    this.runRecordedMotion("currentFind", options)
  }

  runCurrentSearch(options) {
    this.runRecordedMotion("currentSearch", options)
  }

  handleError(error) {
    this.vimState.reset()
    if (!OperationAbortedError) OperationAbortedError = require("./errors")
    if (!(error instanceof OperationAbortedError)) throw error
  }

  isRunning() {
    return this.running
  }

  process() {
    if (this.stack.length === 2) {
      // [FIXME ideally]
      // If target is not complete, we postpone composing target with operator to keep situation simple.
      // So that we can assume when target is set to operator it's complete.
      // e.g. `y s t a'(surround for range from here to till a)
      if (!this.peekTop().isComplete()) return

      const operation = this.stack.pop()
      this.peekTop().setTarget(operation)
    }

    const top = this.peekTop()

    if (!top.isComplete()) {
      if (this.mode === "normal" && top.isOperator()) {
        this.modeManager.activate("operator-pending")
      }
      this.addOperatorSpecificPendingScope(top)
    } else {
      this.execute(this.stack.pop())
    }
  }

  addOperatorSpecificPendingScope(operation) {
    // Temporary set while command is running
    const commandName =
      typeof operation.constructor.getCommandNameWithoutPrefix === "function"
        ? operation.constructor.getCommandNameWithoutPrefix()
        : undefined
    if (commandName) {
      this.addToClassList(commandName + "-pending")
    }
  }

  execute(operation) {
    // Intentionally avoild wrapping by Promise.resolve() to make test easy.
    // Since almost all command don't return promise, finish synchronously.
    const execution = operation.execute()
    if (execution instanceof Promise) {
      execution.then(() => this.finish(operation)).catch(() => this.handleError())
    } else {
      this.finish(operation)
    }
  }

  cancel(operation) {
    if (this.mode === "normal" || this.mode === "operator-pending") {
      this.vimState.resetNormalMode()
      this.vimState.restoreOriginalCursorPosition()
    }
    this.finish(operation)
  }

  finish(operation) {
    if (operation.recordable) this.recordedOperation = operation
    this.lastCommandName = operation.name

    this.vimState.emitDidFinishOperation()
    if (operation.isOperator()) operation.resetState()

    if (this.mode === "normal") {
      this.ensureAllSelectionsAreEmpty(operation)
      this.ensureAllCursorsAreNotAtEndOfLine()
    } else if (this.mode === "visual") {
      this.modeManager.updateNarrowedState()
      this.vimState.updatePreviousSelection()
    }

    this.vimState.cursorStyleManager.refresh()
    this.vimState.reset()
  }

  ensureAllSelectionsAreEmpty(operation) {
    // When @vimState.selectBlockwise() is called in non-visual-mode.
    // e.g. `.` repeat of operation targeted blockwise `CurrentSelection`.
    // We need to manually clear blockwiseSelection.
    // See #647
    this.vimState.clearBlockwiseSelections() // FIXME, should be removed
    if (this.vimState.haveSomeNonEmptySelection()) {
      if (this.vimState.getConfig("strictAssertion")) {
        const message = `Have some non-empty selection in normal-mode: ${operation.toString()}`
        this.vimState.utils.assertWithException(false, message)
      }
      this.vimState.clearSelections()
    }
  }

  ensureAllCursorsAreNotAtEndOfLine() {
    this.editor
      .getCursors()
      .filter(cursor => cursor.isAtEndOfLine())
      .map(cursor => this.vimState.utils.moveCursorLeft(cursor, {preserveGoalColumn: true}))
  }

  addToClassList(className) {
    this.editorElement.classList.add(className)
    this.subscribe(new Disposable(() => this.editorElement.classList.remove(className)))
  }

  // Count
  // -------------------------
  // keystroke `3d2w` delete 6(3*2) words.
  //  2nd number(2 in this case) is always enterd in operator-pending-mode.
  //  So count have two timing to be entered. that's why here we manage counter by mode.
  hasCount() {
    return this.count["normal"] != null || this.count["operator-pending"] != null
  }

  getCount() {
    if (this.hasCount()) {
      return (
        (this.count["normal"] != null ? this.count["normal"] : 1) *
        (this.count["operator-pending"] != null ? this.count["operator-pending"] : 1)
      )
    } else {
      return null
    }
  }

  setCount(number) {
    const mode = this.mode === "operator-pending" ? this.mode : "normal"
    if (this.count[mode] == null) this.count[mode] = 0
    this.count[mode] = this.count[mode] * 10 + number
    this.vimState.hover.set(this.buildCountString())
    this.editorElement.classList.toggle("with-count", true)
  }

  buildCountString() {
    return [this.count["normal"], this.count["operator-pending"]].filter(n => n != null).join("x")
  }

  resetCount() {
    this.count = {}
    this.editorElement.classList.remove("with-count")
  }
}
<|endoftext|>


<commit_before>define([], function() {

	var Vector2 = function(x, y) {
		if(typeof y === "undefined")
			throw Error("initialize Vector2 with less than 2 parameter");

		this.x = x;
		this.y = y;
	};

	Vector2.Zero = new Vector2(0, 0);
	Vector2.One = new Vector2(1, 1);
	Vector2.XAxis = new Vector2(1, 0);
	Vector2.YAxis = new Vector2(0, 1);
	Vector2.fromAngle = function(theta) {
		return new Vector2(Math.cos(theta), Math.sin(theta));
	};

	Vector2.prototype.copy = function() {
		return new Vector2(this.x, this.y);
	};

	Vector2.prototype.set = function(vector) {
		this.x = vector.x;
		this.y = vector.y;
		return this;
	};

	Vector2.prototype.setXY = function(x, y) {
		this.x = x;
		this.y = y;
		return this;
	};

	Vector2.prototype.clear = function() {
		this.x = 0;
		this.y = 0;
	};

	Vector2.prototype.floor = function() {
		return new Vector2(
			Math.floor(this.x),
			Math.floor(this.y)
		);
	};

	Vector2.prototype.floorSelf = function() {
		this.x = Math.floor(this.x);
		this.y = Math.floor(this.y);
	};

	Vector2.prototype.frac = function() {
		return new Vector2(
			this.x - Math.floor(this.x),
			this.y - Math.floor(this.y)
		);
	};

	Vector2.prototype.fracSelf = function() {
		this.x -= Math.floor(this.x);
		this.y -= Math.floor(this.y);
	};

	Vector2.prototype.equals = function(vector) {
		return this.x == vector.x && this.y == vector.y;
	};

	Vector2.prototype.notEquals = function(vector) {
		return this.x != vector.x || this.y != vector.y;
	};

	Vector2.prototype.add = function(vector) {
		return new Vector2(
			this.x + vector.x,
			this.y + vector.y
		);
	};
	Vector2.prototype.addSelf = function(vector) {
		this.x += vector.x;
		this.y += vector.y;
		return this;
	};

	Vector2.prototype.weightedAddSelf = function(vector, scalar) {
		this.x += vector.x * scalar;
		this.y += vector.y * scalar;
		return this;
	};

	Vector2.prototype.sub = function(vector) {
		return new Vector2(
			this.x - vector.x,
			this.y - vector.y
		);
	};
	Vector2.prototype.subSelf = function(vector) {
		this.x -= vector.x;
		this.y -= vector.y;
		return this;
	};

	// scaling!
	Vector2.prototype.mulFloat = function(right) {
		return new Vector2(
			this.x * right,
			this.y * right
		);
	};
	Vector2.prototype.mulFloatSelf = function(right) {
		this.x *= right;
		this.y *= right;
		return this;
	};

	Vector2.prototype.divFloat = function(right) {
		var inv = 1.0 / right;
		return new Vector2(
			this.x * inv,
			this.y * inv
		);
	};
	Vector2.prototype.divFloatSelf = function(right) {
		this.x /= right;
		this.y /= right;
		return this;
	};

	// per-element multiplication
	Vector2.prototype.mulVector = function(right) {
		return new Vector2(
			this.x * right.x,
			this.y * right.y
		);
	};
	Vector2.prototype.mulVectorSelf = function(right) {
		this.x *= right.x;
		this.y *= right.y;
		return this;
	};

	Vector2.prototype.divVector = function(right) {
		return new Vector2(
			this.x / right.x,
			this.y / right.y
		);
	};
	Vector2.prototype.divVectorSelf = function(right) {
		this.x /= right.x;
		this.y /= right.y;
		return this;
	};

	Vector2.prototype.positive = function() { return this; };
	Vector2.prototype.negative = function() {
		return new Vector2(-this.x, -this.y);
	};

	// helpers

	Vector2.prototype.length = function() {
		return Math.sqrt(this.x*this.x + this.y*this.y);
	};
	Vector2.prototype.lengthSquared = function() {
		return this.x*this.x + this.y*this.y;
	};
	Vector2.prototype.distance = function(right) {
		var x = this.x - right.x;
		var y = this.y - right.y;
		return Math.sqrt(x*x + y*y);
	};
	Vector2.prototype.distanceSquared = function(right) {
		var x = this.x - right.x;
		var y = this.y - right.y;
		return x*x + y*y;
	};
	Vector2.prototype.normalize = function() {
		var length = Math.sqrt(this.x*this.x + this.y*this.y);
		if(length > 1e-08) {
			var invL = 1.0 / length;
			this.x *= invL;
			this.y *= invL;
		}
		return length;
	};

	Vector2.prototype.normalizedCopy = function() {
		var ret = this.copy();
		ret.normalize();
		return ret;
	};

	Vector2.prototype.dotProduct = function(vector) {
		return this.x*vector.x + this.y*vector.y;
	};

	Vector2.prototype.getPerpendicular = function() {
		return this.getRightPerpendicular();
	};

	Vector2.prototype.getLeftPerpendicular = function() {
		var x = this.y;
		var y = -1 * this.x;
		return new Vector2(x, y);
	};

	Vector2.prototype.getRightPerpendicular = function() {
		var x = -1 * this.y;
		var y = this.x;
		return new Vector2(x, y);
	};

	Vector2.prototype.makePerpendicular = function() {
		var tempX = this.x;
		this.x = -this.y;
		this.y = tempX;
	};

	Vector2.prototype.crossProduct = function(vector) {
		return this.x * vector.y + this.y * vector.x;
	};

	Vector2.prototype.lerp = function(to, i) {
		return this.add(to.sub(this).mulFloat(i));
	};

	Vector2.prototype.lerpSelf = function(to, i) {
		return this.weightedAddSelf(to.sub(this), i);
	};

	Vector2.prototype.slerp = function(to, i) {
		return this.add(to.sub(this).mulFloat(
			0.5 + (Math.sin((3.141592654 * i) - 1.570796) * 0.5)));
	};

	Vector2.prototype.rotate = function(theta) {
		var co = Math.cos(theta);
		var si = Math.sin(theta);
		return new Vector2(
			co * this.x - si * this.y,
			si * this.x + co * this.y
		);
	};

	Vector2.prototype.rotateSelf = function(theta) {
		var co = Math.cos(theta);
		var si = Math.sin(theta);
		var xx = co * this.x - si * this.y;
		this.y = si * this.x + co * this.y;
		this.x = xx;
	};

	Vector2.prototype.reflectOnNormal = function(normal) {
		//v' = 2 * (v . n) * n - v
		var newVector =
			this.sub(
				normal
				.mulFloat(this.dotProduct(normal))
				.mulFloat(2)
			);
		return newVector;

	};

	Vector2.prototype.toCartesian = function() {
		return new Vector2(
			this.x * Math.cos(this.y),
			this.x * Math.sin(this.y)
		);
	};

	Vector2.prototype.toPolar = function() {
		return new Vector2(
			Math.sqrt(this.x * this.x + this.y * this.y),
			Math.atan2(this.y, this.x)
		);
	};

	Vector2.prototype.signum = function() {
		return new Vector2(
			this.x.sign(),
			this.y.sign()
		);
	};

	Vector2.prototype.toJson = function() {
		var resultJson = {
			"x": this.x,
			"y": this.y
		};

		return resultJson;
	};

	Vector2.fromJson = function(vectorJson) {
		return new Vector2(vectorJson.x, vectorJson.y);
	};

	return Vector2;
});

<commit_msg>added getDirectedAngle method to Jello.Vector2<commit_after>define([], function() {

	var Vector2 = function(x, y) {
		if(typeof y === "undefined")
			throw Error("initialize Vector2 with less than 2 parameter");

		this.x = x;
		this.y = y;
	};

	Vector2.Zero = new Vector2(0, 0);
	Vector2.One = new Vector2(1, 1);
	Vector2.XAxis = new Vector2(1, 0);
	Vector2.YAxis = new Vector2(0, 1);
	Vector2.fromAngle = function(theta) {
		return new Vector2(Math.cos(theta), Math.sin(theta));
	};

	Vector2.prototype.copy = function() {
		return new Vector2(this.x, this.y);
	};

	Vector2.prototype.set = function(vector) {
		this.x = vector.x;
		this.y = vector.y;
		return this;
	};

	Vector2.prototype.setXY = function(x, y) {
		this.x = x;
		this.y = y;
		return this;
	};

	Vector2.prototype.clear = function() {
		this.x = 0;
		this.y = 0;
	};

	Vector2.prototype.floor = function() {
		return new Vector2(
			Math.floor(this.x),
			Math.floor(this.y)
		);
	};

	Vector2.prototype.floorSelf = function() {
		this.x = Math.floor(this.x);
		this.y = Math.floor(this.y);
	};

	Vector2.prototype.frac = function() {
		return new Vector2(
			this.x - Math.floor(this.x),
			this.y - Math.floor(this.y)
		);
	};

	Vector2.prototype.fracSelf = function() {
		this.x -= Math.floor(this.x);
		this.y -= Math.floor(this.y);
	};

	Vector2.prototype.equals = function(vector) {
		return this.x == vector.x && this.y == vector.y;
	};

	Vector2.prototype.notEquals = function(vector) {
		return this.x != vector.x || this.y != vector.y;
	};

	Vector2.prototype.add = function(vector) {
		return new Vector2(
			this.x + vector.x,
			this.y + vector.y
		);
	};
	Vector2.prototype.addSelf = function(vector) {
		this.x += vector.x;
		this.y += vector.y;
		return this;
	};

	Vector2.prototype.weightedAddSelf = function(vector, scalar) {
		this.x += vector.x * scalar;
		this.y += vector.y * scalar;
		return this;
	};

	Vector2.prototype.sub = function(vector) {
		return new Vector2(
			this.x - vector.x,
			this.y - vector.y
		);
	};
	Vector2.prototype.subSelf = function(vector) {
		this.x -= vector.x;
		this.y -= vector.y;
		return this;
	};

	// scaling!
	Vector2.prototype.mulFloat = function(right) {
		return new Vector2(
			this.x * right,
			this.y * right
		);
	};
	Vector2.prototype.mulFloatSelf = function(right) {
		this.x *= right;
		this.y *= right;
		return this;
	};

	Vector2.prototype.divFloat = function(right) {
		var inv = 1.0 / right;
		return new Vector2(
			this.x * inv,
			this.y * inv
		);
	};
	Vector2.prototype.divFloatSelf = function(right) {
		this.x /= right;
		this.y /= right;
		return this;
	};

	// per-element multiplication
	Vector2.prototype.mulVector = function(right) {
		return new Vector2(
			this.x * right.x,
			this.y * right.y
		);
	};
	Vector2.prototype.mulVectorSelf = function(right) {
		this.x *= right.x;
		this.y *= right.y;
		return this;
	};

	Vector2.prototype.divVector = function(right) {
		return new Vector2(
			this.x / right.x,
			this.y / right.y
		);
	};
	Vector2.prototype.divVectorSelf = function(right) {
		this.x /= right.x;
		this.y /= right.y;
		return this;
	};

	Vector2.prototype.positive = function() { return this; };
	Vector2.prototype.negative = function() {
		return new Vector2(-this.x, -this.y);
	};

	// helpers

	Vector2.prototype.length = function() {
		return Math.sqrt(this.x*this.x + this.y*this.y);
	};
	Vector2.prototype.lengthSquared = function() {
		return this.x*this.x + this.y*this.y;
	};
	Vector2.prototype.distance = function(right) {
		var x = this.x - right.x;
		var y = this.y - right.y;
		return Math.sqrt(x*x + y*y);
	};
	Vector2.prototype.distanceSquared = function(right) {
		var x = this.x - right.x;
		var y = this.y - right.y;
		return x*x + y*y;
	};
	Vector2.prototype.normalize = function() {
		var length = Math.sqrt(this.x*this.x + this.y*this.y);
		if(length > 1e-08) {
			var invL = 1.0 / length;
			this.x *= invL;
			this.y *= invL;
		}
		return length;
	};

	Vector2.prototype.normalizedCopy = function() {
		var ret = this.copy();
		ret.normalize();
		return ret;
	};

	Vector2.prototype.dotProduct = function(vector) {
		return this.x*vector.x + this.y*vector.y;
	};

	Vector2.prototype.getPerpendicular = function() {
		return this.getRightPerpendicular();
	};

	Vector2.prototype.getLeftPerpendicular = function() {
		var x = this.y;
		var y = -1 * this.x;
		return new Vector2(x, y);
	};

	Vector2.prototype.getRightPerpendicular = function() {
		var x = -1 * this.y;
		var y = this.x;
		return new Vector2(x, y);
	};

	Vector2.prototype.makePerpendicular = function() {
		var tempX = this.x;
		this.x = -this.y;
		this.y = tempX;
	};

	Vector2.prototype.crossProduct = function(vector) {
		return this.x * vector.y + this.y * vector.x;
	};

	Vector2.prototype.lerp = function(to, i) {
		return this.add(to.sub(this).mulFloat(i));
	};

	Vector2.prototype.lerpSelf = function(to, i) {
		return this.weightedAddSelf(to.sub(this), i);
	};

	Vector2.prototype.slerp = function(to, i) {
		return this.add(to.sub(this).mulFloat(
			0.5 + (Math.sin((3.141592654 * i) - 1.570796) * 0.5)));
	};

	Vector2.prototype.rotate = function(theta) {
		var co = Math.cos(theta);
		var si = Math.sin(theta);
		return new Vector2(
			co * this.x - si * this.y,
			si * this.x + co * this.y
		);
	};

	Vector2.prototype.rotateSelf = function(theta) {
		var co = Math.cos(theta);
		var si = Math.sin(theta);
		var xx = co * this.x - si * this.y;
		this.y = si * this.x + co * this.y;
		this.x = xx;
	};

	// get (signed and directional) angle between this and the given vector in degrees
	Vector2.prototype.getDirectedAngle = function(point) {
		return Math.atan2(this.crossProduct(point), this.dotProduct(point)) * 180 / Math.PI;
	};

	Vector2.prototype.reflectOnNormal = function(normal) {
		//v' = 2 * (v . n) * n - v
		var newVector =
			this.sub(
				normal
				.mulFloat(this.dotProduct(normal))
				.mulFloat(2)
			);
		return newVector;

	};

	Vector2.prototype.toCartesian = function() {
		return new Vector2(
			this.x * Math.cos(this.y),
			this.x * Math.sin(this.y)
		);
	};

	Vector2.prototype.toPolar = function() {
		return new Vector2(
			Math.sqrt(this.x * this.x + this.y * this.y),
			Math.atan2(this.y, this.x)
		);
	};

	Vector2.prototype.signum = function() {
		return new Vector2(
			this.x.sign(),
			this.y.sign()
		);
	};

	Vector2.prototype.toJson = function() {
		var resultJson = {
			"x": this.x,
			"y": this.y
		};

		return resultJson;
	};

	Vector2.fromJson = function(vectorJson) {
		return new Vector2(vectorJson.x, vectorJson.y);
	};

	return Vector2;
});

<|endoftext|>


<commit_before>alert("editadodos");
<commit_msg>update archivo js <commit_after>alert("editadodos");
console.log("cambios desde consola");
<|endoftext|>


<commit_before>
var jq = null;
var KillKat =
{
	init: 	function(){
        if (confirm("Ready to kill Katz ??"))
        {
            KillKat.loadStaticFiles();
            KillKat.initImagesHandler();
        }
	},
    sound: null,
    domImgs : [],
    listImgs : [],
	IMG_MIN_WIDTH : 100,
	IMG_MIN_HEIGHT : 100,
	KILL_TAG: 'killkat-shot',
    OVERLAY_TAG: 'killkat-overlay',
    GITHUB : "https://rawgit.com/jorisgrouillet/killkat/master",
    requirements: {
        'min-dimensions' : function(img){ return ((img.width * img.height) > (KillKat.IMG_MIN_WIDTH * KillKat.IMG_MIN_HEIGHT)); }
    },

    loadStaticFiles: function()
    {
        var stylesheet = document.createElement('link');
        stylesheet.href = KillKat.GITHUB+'/css/killkat.css';
        stylesheet.rel = 'stylesheet';
        stylesheet.type = 'text/css';
        document.getElementsByTagName('head')[0].appendChild(stylesheet);
    },
	initImagesHandler : function()
	{
        KillKat.domImgs = jq('img');
        KillKat.domImgs.each(
			function(idx, domImg){
				KillKat.filterImg(domImg);

			}
		);
	},

	filterImg : function(domImg)
	{
		if (KillKat.meetRequirements(domImg)){
			KillKat.addToListImgs(domImg);
		}
	},

	meetRequirements : function(domImg)
	{
		var reqs = KillKat.requirements || [];
		var validateReqs = true;
		for (var rIdx in reqs){
			if (typeof(reqs[rIdx]) == 'function'){
				validateReqs &= reqs[rIdx].call(this, domImg);
			}
		}
		return (validateReqs===1);
	},

	addToListImgs: function(domImg)
	{
		jqImg = KillKat.overrideClickEvent(domImg);
		KillKat.listImgs.push(jqImg);
	},

	overrideClickEvent: function(domImg)
	{
		var jqImg = jq(domImg);
		var fct = KillKat.getClickEventFunction();
		jqImg.unbind('click').click(fct);
		return jqImg;
	},
	getClickEventFunction: function()
	{
		return function(e){
            e.preventDefault();
			KillKat.handleTarget(this);
            KillKat.convertImgToBase64(this.src, function(dataUrl){
                console.log(dataUrl);
            });
			return false;
		};
	},
	handleTarget: function(domImg)
	{
		var jqImg = jq(domImg);
        KillKat.setOverlay(jqImg);
	},
    setOverlay: function(jqImg)
    {
        var imgContainer = jqImg.closest('div');
        //imgContainer.css('z-index', 99);
        var imgIndex = (KillKat.getImgIndex(jqImg)).toString();
        var domOverlay = jq('#killkat-tag-'+imgIndex);

        if (! domOverlay.length)
        {
            domOverlay = jq('

')
                            .css({  'width' : jqImg.innerWidth(),
                                    'height' : jqImg.innerHeight(),
                                    'top' : jqImg.offset().top,
                                    'left' : jqImg.offset().left,
                                    'z-index': 1
                                })
                            .appendTo(jq('body'));

            KillKat.playSound();
            return;
        }

        if (domOverlay.is(':visible')){
            domOverlay.fadeOut(1000);
        }
        else{
            domOverlay.show();
            KillKat.playSound();
        }
    },

	isKatKilled: function(jqImg)
	{
		return (jqImg.parent().hasClass(KillKat.KILL_TAG));
	},

    getImgIndex : function(jqImg)
    {
        return KillKat.domImgs.index(jqImg);
    },
    playSound : function()
    {
        if (! jq('#killkat-sound').length){
            KillKat.setSoundPlayer();
        }
        KillKat.sound.play();
    },
    setSoundPlayer: function()
    {
        if (! jq('#killkat-sound').length)
        {
            var sound = jq('<audio id="killkat-sound" preload="auto" autoplay>'+
                '<source src="'+KillKat.GITHUB+'/audio/splatter-sound.mp3" type="audio/mp3" />'+
                            //'<source src="http://www.freesfx.co.uk/rx2/mp3s/2/1871_1272479313.mp3" type="audio/mp3" />'+
                            'Votre navigateur n\'est pas compatible'+
                            '</audio>');

            jq('body').append(sound);
            KillKat.sound = sound.get(0);
        }
    },
	convertImgToBase64 : function(url, callback, outputFormat)
	{
	    var canvas = document.createElement('canvas'),
	    ctx = canvas.getContext('2d'),
	    img = new Image();
	    img.crossOrigin = 'Anonymous';
	    img.onload = function(){
	        canvas.height = img.height;
	        canvas.width = img.width;
	        ctx.drawImage(img,0,0);
	        var dataURL = canvas.toDataURL(outputFormat || 'image/png');
	        callback.call(this, dataURL);
	        canvas = null;
	    };
	    img.src = url;
	}
};

(function (_callback) {

    function loadScript(url, callback) {

        var script = document.createElement("script")
        script.type = "text/javascript";

        if (script.readyState) { //IE
            script.onreadystatechange = function () {
                if (script.readyState == "loaded" || script.readyState == "complete") {
                    script.onreadystatechange = null;
                    callback();
                }
            };
        } else { //Others
            script.onload = function () {
			jq = jQuery;
                callback();
            };
        }

        script.src = url;
        document.getElementsByTagName("head")[0].appendChild(script);
    }

    loadScript("//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {

         //jQuery loaded
         console.log('jquery loaded');
		 _callback.call(this);
    });

})( function(){  KillKat.init();});
<commit_msg>ajout const de classe icon-killable ajout id du div de l’icon-killable la fonction setIconKillable est apposée dès la surcharge du click plutôt qu’au moment du shoot<commit_after>
var jq = null;
var KillKat =
{
	init: 	function(){
        if (confirm("Ready to kill Katz ??"))
        {
            KillKat.loadStaticFiles();
            KillKat.initImagesHandler();
            KillKat.setSoundPlayer();
        }
	},
    sound: null,
    domImgs : [],
    listImgs : [],
    icons: {
       iconKillable: {
            width: '20px',
            height: '20px'
       }
    },
	IMG_MIN_WIDTH : 100,
	IMG_MIN_HEIGHT : 100,
	KILL_TAG: 'killkat-shot',
    OVERLAY_TAG: 'killkat-overlay',
    KILLABLE_TAG : 'killkat-icon-killable',
    GITHUB : "https://rawgit.com/jorisgrouillet/killkat/master",

    requirements: {
        'min-dimensions' : function(img){ return ((img.width * img.height) > (KillKat.IMG_MIN_WIDTH * KillKat.IMG_MIN_HEIGHT)); }
    },

    loadStaticFiles: function()
    {
        var stylesheet = document.createElement('link');
        stylesheet.href = KillKat.GITHUB+'/css/killkat.css';
        stylesheet.rel = 'stylesheet';
        stylesheet.type = 'text/css';
        document.getElementsByTagName('head')[0].appendChild(stylesheet);
    },
	initImagesHandler : function()
	{
        KillKat.domImgs = jQuery('img');
        KillKat.domImgs.each(
			function(idx, domImg){
				KillKat.filterImg(domImg);

			}
		);
	},

	filterImg : function(domImg)
	{
		if (KillKat.meetRequirements(domImg)){
			KillKat.addToListImgs(domImg);
		}
	},

	meetRequirements : function(domImg)
	{
		var reqs = KillKat.requirements || [];
		var validateReqs = true;
		for (var rIdx in reqs){
			if (typeof(reqs[rIdx]) == 'function'){
				validateReqs &= reqs[rIdx].call(this, domImg);
			}
		}
		return (validateReqs===1);
	},

	addToListImgs: function(domImg)
	{
		jqImg = KillKat.overrideClickEvent(domImg);
		KillKat.listImgs.push(jqImg);
	},

	overrideClickEvent: function(domImg)
	{
		var jqImg = jQuery(domImg);
		var fct = KillKat.getClickEventFunction();
		jqImg.unbind('click').click(fct);
        KillKat.setIconKillable(jqImg, KillKat.getImgIndex(jqImg));
		return jqImg;
	},
	getClickEventFunction: function()
	{
		return function(e){
            e.preventDefault();
			KillKat.handleTarget(this);
            KillKat.convertImgToBase64(this.src, function(dataUrl){
                console.log(dataUrl);
            });
			return false;
		};
	},
	handleTarget: function(domImg)
	{
		var jqImg = jQuery(domImg);
        KillKat.setOverlay(jqImg, KillKat.getImgIndex(jqImg));
    },
    setOverlay: function(jqImg, imgIndex)
    {
        var domOverlay = jQuery('#killkat-tag-'+imgIndex);

        if (! domOverlay.length)
        {
            domOverlay = jQuery('

')
                            .css({  'width' : jqImg.innerWidth(),
                                    'height' : jqImg.innerHeight(),
                                    'top' : jqImg.offset().top,
                                    'left' : jqImg.offset().left,
                                })
                            .appendTo(jQuery('body'));

            KillKat.playSound();
            return;
        }

        if (domOverlay.is(':visible')){
            domOverlay.fadeOut(1000);
        }
        else{
            domOverlay.show();
            KillKat.playSound();
        }
    },
    setIconKillable: function(jqImg, imgIndex) {

        var domIconKillable = jQuery('#killkat-killable-'+imgIndex);
        if (! domIconKillable.length)
        {
            jQuery('

')
                .css({
                    'top' : (jqImg.offset().top - (parseInt(KillKat.icons.iconKillable.height)/2)),
                    'left' : (jqImg.width() + jqImg.offset().left - parseInt(KillKat.icons.iconKillable.width)/2),
                })
                .appendTo(jQuery('body'));
        }
    },

	isKatKilled: function(jqImg)
	{
		return (jqImg.parent().hasClass(KillKat.KILL_TAG));
	},

    getImgIndex : function(jqImg)
    {
        return KillKat.domImgs.index(jqImg);
    },
    playSound : function()
    {
        if (! jQuery('#killkat-sound').length){
            KillKat.setSoundPlayer();
        }
        KillKat.sound.play();
    },
    setSoundPlayer: function()
    {
        if (! jQuery('#killkat-sound').length)
        {
            var sound = jQuery('<audio id="killkat-sound" preload="auto">'+
                '<source src="'+KillKat.GITHUB+'/audio/splatter-sound.mp3" type="audio/mp3" />'+
                            //'<source src="http://www.freesfx.co.uk/rx2/mp3s/2/1871_1272479313.mp3" type="audio/mp3" />'+
                            'Votre navigateur n\'est pas compatible'+
                            '</audio>');

            jQuery('body').append(sound);
            KillKat.sound = sound.get(0);
        }
    },
	convertImgToBase64 : function(url, callback, outputFormat)
	{
	    var canvas = document.createElement('canvas'),
	    ctx = canvas.getContext('2d'),
	    img = new Image();
	    img.crossOrigin = 'Anonymous';
	    img.onload = function(){
	        canvas.height = img.height;
	        canvas.width = img.width;
	        ctx.drawImage(img,0,0);
	        var dataURL = canvas.toDataURL(outputFormat || 'image/png');
	        callback.call(this, dataURL);
	        canvas = null;
	    };
	    img.src = url;
	}
};

(function (_callback) {

    function loadScript(url, callback) {

        var script = document.createElement("script")
        script.type = "text/javascript";

        if (script.readyState) { //IE
            script.onreadystatechange = function () {
                if (script.readyState == "loaded" || script.readyState == "complete") {
                    script.onreadystatechange = null;
                    callback();
                }
            };
        } else { //Others
            script.onload = function () {
			jq = jQuery;
                callback();
            };
        }

        script.src = url;
        document.getElementsByTagName("head")[0].appendChild(script);
    }

    loadScript("//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {

         //jQuery loaded
         console.log('jquery loaded');
		 _callback.call(this);
    });

})( function(){  KillKat.init();});
<|endoftext|>


<commit_before>var exec = require('phonegap/exec'),
    ContactError = require('phonegap/plugin/ContactError'),
    Contact = require('phonegap/plugin/Contact');

/**
* Represents a group of Contacts.
* @constructor
*/
var contacts = {
    /**
     * Returns an array of Contacts matching the search criteria.
     * @param fields that should be searched
     * @param successCB success callback
     * @param errorCB error callback
     * @param {ContactFindOptions} options that can be applied to contact searching
     * @return array of Contacts matching search criteria
     */
    find:function(fields, successCB, errorCB, options) {
        if (successCB === null) {
            throw new TypeError("You must specify a success callback for the find command.");
        }
        if (fields === null || fields === "undefined" || fields.length === "undefined" || fields.length <= 0) {
            if (typeof errorCB === "function") {
                errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
            }
        } else {
            var win = function(result) {
                var cs = [];
                for (var i = 0, l = result.message.length; i < l; i++) {
                    cs.push(contacts.create(result.message[i]));
                }
                successCB(cs);
            };
            exec(win, errorCB, "Contacts", "search", [fields, options]);
        }
    },

    /**
     * This function creates a new contact, but it does not persist the contact
     * to device storage. To persist the contact to device storage, invoke
     * contact.save().
     * @param properties an object who's properties will be examined to create a new Contact
     * @returns new Contact object
     */
    create:function(properties) {
        var i;
        var contact = new Contact();
        for (i in properties) {
            if (typeof contact[i] !== 'undefined' && properties.isOwnProperty(i)) {
                contact[i] = properties[i];
            }
        }
        return contact;
    }
};

module.exports = contacts;
<commit_msg>fixing up contacts!<commit_after>var exec = require('phonegap/exec'),
    ContactError = require('phonegap/plugin/ContactError'),
    Contact = require('phonegap/plugin/Contact');

/**
* Represents a group of Contacts.
* @constructor
*/
var contacts = {
    /**
     * Returns an array of Contacts matching the search criteria.
     * @param fields that should be searched
     * @param successCB success callback
     * @param errorCB error callback
     * @param {ContactFindOptions} options that can be applied to contact searching
     * @return array of Contacts matching search criteria
     */
    find:function(fields, successCB, errorCB, options) {
        if (successCB === null) {
            throw new TypeError("You must specify a success callback for the find command.");
        }
        if (fields === null || fields === "undefined" || fields.length === "undefined" || fields.length <= 0) {
            if (typeof errorCB === "function") {
                errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
            }
        } else {
            var win = function(result) {
                var cs = [];
                for (var i = 0, l = result.length; i < l; i++) {
                    cs.push(contacts.create(result[i]));
                }
                successCB(cs);
            };
            exec(win, errorCB, "Contacts", "search", [fields, options]);
        }
    },

    /**
     * This function creates a new contact, but it does not persist the contact
     * to device storage. To persist the contact to device storage, invoke
     * contact.save().
     * @param properties an object who's properties will be examined to create a new Contact
     * @returns new Contact object
     */
    create:function(properties) {
        var i;
        var contact = new Contact();
        for (i in properties) {
            if (typeof contact[i] !== 'undefined' && properties.hasOwnProperty(i)) {
                contact[i] = properties[i];
            }
        }
        return contact;
    }
};

module.exports = contacts;
<|endoftext|>


<commit_before>'use strict';

var Good = require('good');
var Path = require('path');
var Hoek = require('hoek');
//TODO: make all log events go through chalk and paint red/green according to tags
//var Chalk = require('chalk');
var Package = require('../../package.json');
var Config = require('../config');

var internals = {};
internals.options = {
    ops: {
        interval: Config.monitor.interval
    },
    reporters: {}
};

internals.options.reporters.console = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        log: {
            exclude: 'debug'
        }
    }]
}, {
    module: 'good-console',
    args: [{
        format: Config.monitor.format
    }]
}, 'stdout'];

//TODO: use rotating file stream
//https://github.com/hapijs/good/blob/master/examples/log-to-file.md

internals.options.reporters.ops = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        ops: '*'
    }]
}, {
    module: 'good-squeeze',
    name: 'SafeJson'
}, {
    module: 'good-file',
    args: [Path.resolve(Config.monitor.path, Package.name + '-' + Package.version + '-ops.log')]
}];

internals.options.reporters.access = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        response: '*'
    }]
}, {
    module: 'good-console',
    args: [{
        format: Config.monitor.format,
        color: false
    }]
}, {
    module: 'good-file',
    args: [Path.resolve(Config.monitor.path, Package.name + '-' + Package.version + '-access.log')]
}];

internals.options.reporters.ops = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        log: {
            include: 'auth'
        }
    }]
}, {
    module: 'good-console',
    args: [{
        format: Config.monitor.format,
        color: false
    }]
}, {
    module: 'good-file',
    args: [Path.resolve(Config.monitor.path, Package.name + '-' + Package.version + '-auth.log')]
}];

internals.options.reporters.error = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        log: {
            include: 'error'
        }
    }]
}, {
    module: 'good-console',
    args: [{
        format: Config.monitor.format,
        color: false
    }]
}, {
    module: 'good-file',
    args: [Path.resolve(Config.monitor.path, Package.name + '-' + Package.version + '-error.log')]
}];

exports.register = function(server, options, next) {

    // add route and access logs to console
    if (Config.monitor.debug) {
        internals.options.reporters.console[0].args[0] = {
            log: '*',
            response: '*',
            route: '*'
        };
    } else {
        internals.options.reporters.console[0].args[0] = {
            log: {
                exclude: ['debug', 'client']
            }
        };
    }

    //TODO: would be nice to color these like good-console does with response events
    server.on('route', function(event) {
        server.log(['server', 'route', 'debug'], {
            plugin: event.realm.plugin,
            method: event.method,
            path: event.path
        });
    });

    server.on('request', function(request, event) {

        var data = Hoek.clone(event.data);

        if (!data) {
            data = {};
        }

        if (typeof data === 'string') {
            data = {
                message: event.data
            };
        }

        Hoek.assert(typeof data === 'object', 'Incorrect usage of request.log()');

        if (Config.monitor.debug) {

            // include the hapi request id, path and ip address
            data.request = event.request.split(':')[3];
            data.path = request.url.path;
            data.address = request.headers['x-forwarded-for'] || request.info.remoteAddress;

        }

        server.log(event.tags, data);

    });

    // Log all internal server errors to error log
    server.ext('onPreResponse', function (request, reply) {

        var response = request.response;
        if (response.isBoom && response.isServer) {
            request.log(['error'], response.data);
        }

        return reply.continue();
    });

    //TODO: would be nice to color these like good-console does with response events
    server.on('response', function(request) {

        if (!request.response.source) {
            return;
        }

        server.log(['response', 'debug'], request.response.source);
    });

    server.register({
        register: Good,
        options: internals.options
    }, function(err) {

        if (err) {
            return next(err);
        }

        return next();
    });
};

exports.register.attributes = {
    name: 'monitor',
    pkg: Package
};
<commit_msg>log response payload for api connection only<commit_after>'use strict';

var Good = require('good');
var Path = require('path');
var Hoek = require('hoek');
//TODO: make all log events go through chalk and paint red/green according to tags
//var Chalk = require('chalk');
var Package = require('../../package.json');
var Config = require('../config');

var internals = {};
internals.options = {
    ops: {
        interval: Config.monitor.interval
    },
    reporters: {}
};

internals.options.reporters.console = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        log: {
            exclude: 'debug'
        }
    }]
}, {
    module: 'good-console',
    args: [{
        format: Config.monitor.format
    }]
}, 'stdout'];

//TODO: use rotating file stream
//https://github.com/hapijs/good/blob/master/examples/log-to-file.md

internals.options.reporters.ops = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        ops: '*'
    }]
}, {
    module: 'good-squeeze',
    name: 'SafeJson'
}, {
    module: 'good-file',
    args: [Path.resolve(Config.monitor.path, Package.name + '-' + Package.version + '-ops.log')]
}];

internals.options.reporters.access = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        response: '*'
    }]
}, {
    module: 'good-console',
    args: [{
        format: Config.monitor.format,
        color: false
    }]
}, {
    module: 'good-file',
    args: [Path.resolve(Config.monitor.path, Package.name + '-' + Package.version + '-access.log')]
}];

internals.options.reporters.ops = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        log: {
            include: 'auth'
        }
    }]
}, {
    module: 'good-console',
    args: [{
        format: Config.monitor.format,
        color: false
    }]
}, {
    module: 'good-file',
    args: [Path.resolve(Config.monitor.path, Package.name + '-' + Package.version + '-auth.log')]
}];

internals.options.reporters.error = [{
    module: 'good-squeeze',
    name: 'Squeeze',
    args: [{
        log: {
            include: 'error'
        }
    }]
}, {
    module: 'good-console',
    args: [{
        format: Config.monitor.format,
        color: false
    }]
}, {
    module: 'good-file',
    args: [Path.resolve(Config.monitor.path, Package.name + '-' + Package.version + '-error.log')]
}];

exports.register = function(server, options, next) {

    // add route and access logs to console
    if (Config.monitor.debug) {
        internals.options.reporters.console[0].args[0] = {
            log: '*',
            response: '*',
            route: '*'
        };
    } else {
        internals.options.reporters.console[0].args[0] = {
            log: {
                exclude: ['debug', 'client']
            }
        };
    }

    //TODO: would be nice to color these like good-console does with response events
    server.on('route', function(event) {
        server.log(['server', 'route', 'debug'], {
            plugin: event.realm.plugin,
            method: event.method,
            path: event.path
        });
    });

    server.on('request', function(request, event) {

        var data = Hoek.clone(event.data);

        if (!data) {
            data = {};
        }

        if (typeof data === 'string') {
            data = {
                message: event.data
            };
        }

        Hoek.assert(typeof data === 'object', 'Incorrect usage of request.log()');

        if (Config.monitor.debug) {

            // include the hapi request id, path and ip address
            data.request = event.request.split(':')[3];
            data.path = request.url.path;
            data.address = request.headers['x-forwarded-for'] || request.info.remoteAddress;

        }

        server.log(event.tags, data);

    });

    // Log all internal server errors to error log
    server.ext('onPreResponse', function (request, reply) {

        var response = request.response;
        if (response.isBoom && response.isServer) {
            request.log(['error'], response.data);
        }

        return reply.continue();
    });

    //TODO: would be nice to color these like good-console does with response events
    // log the payload for all api connection responses
    server.select('api').on('response', function(request) {

        if (!request.response.source) {
            return;
        }

        server.log(['response', 'debug'], request.response.source);

    });

    server.register({
        register: Good,
        options: internals.options
    }, function(err) {

        if (err) {
            return next(err);
        }

        return next();
    });
};

exports.register.attributes = {
    name: 'monitor',
    pkg: Package
};
<|endoftext|>


<commit_before>REQUIRED_ENVIRONMENT_VARIABLES = [
    'WEBHOOK_LISTENER_GITHUB_WEBHOOK_PORT',
    'WEBHOOK_LISTENER_SLACK_HOOK_TOKEN'
];
MISSING_VARIABLES = [];
REQUIRED_ENVIRONMENT_VARIABLES.forEach(function (variableName) {
    if (!process.env[variableName]) {
        MISSING_VARIABLES.push(variableName);
    }
});
if (MISSING_VARIABLES.length > 0) {
    var message = 'Missing environment variables: ' + MISSING_VARIABLES.join(', ');
    console.error(message);
    throw new Error(message);
}

process.env.TZ = 'Europe/Warsaw';

var gith = require('gith').create(process.env.WEBHOOK_LISTENER_GITHUB_WEBHOOK_PORT);
var execFile = require('child_process').execFile;
var nodeSlackr = require('node-slackr');

var slack = new nodeSlackr(process.env.WEBHOOK_LISTENER_SLACK_HOOK_TOKEN);

function sendMessageToSlack(message) {
    var formattedDate = '`' + new Date() + '`\n';
    var messages = {
        text: formattedDate + message,
        channel: '#builds'
    };
    slack.notify(messages, function (err, result) {
        if (!err) {
            console.log('Sent message: ');
            console.log(messages);
        } else {
            console.error('Something went wrong in sending message: ');
            console.error(err);
            console.error(messages);
        }
    });
}

sendMessageToSlack('*Siema Heniu*');

var targets = [
    {
        repo: 'codepotpl/codepot',
        branch: 'production',
        appName: 'WEBSITE PRODUCTION',
        script: './codepot-production.sh'
    },
    {
        repo: 'codepotpl/codepot',
        branch: 'master',
        appName: 'WEBSITE STAGING',
        script: './codepot-staging.sh'
    },
    {
        repo: 'codepotpl/codepot-webclient',
        branch: 'master',
        appName: 'WEBCLIENT STAGING',
        script: './codepot-webclient-staging.sh'
    },
    {
        repo: 'codepotpl/codepot-backend',
        branch: 'master',
        appName: 'BACKEND STAGING',
        script: './codepot-backend-staging.sh'
    },
    {
        repo: 'codepotpl/codepot-backend',
        branch: 'production',
        appName: 'BACKEND PRODUCTION',
        script: './codepot-backend-production.sh'
    }
];

targets.forEach(function (target) {
    gith({
        repo: target.repo,
        branch: target.branch
    }).on('all', function (payload) {
        var message = '------ *' + target.repo + ':' + target.branch + '* changed ------\nPusher: `' + payload.pusher + '`.\n\nBuilding and running new ' + target.appName;
        sendMessageToSlack(message);

        var startDate = new Date();
        execFile(target.script, function (error, stdout, stderr) {
            var message;
            if (!error) {
                message = '*' + target.appName + ' build complete! Hooray!*';
            } else {
                message = '*' + target.appName + ' build failed!*.\nMore info below:\n\n```' + error + '```';
                console.error('Something went wrong in ' + target.appName + ' build.');
                console.error(error);
            }
            sendMessageToSlack(target.appName + ' build time: `' + (new Date() - startDate) / 1000.0 + '`.\n' + message);
        });
    });
});<commit_msg>listener with codeo<commit_after>REQUIRED_ENVIRONMENT_VARIABLES = [
    'WEBHOOK_LISTENER_GITHUB_WEBHOOK_PORT',
    'WEBHOOK_LISTENER_SLACK_HOOK_TOKEN'
];
MISSING_VARIABLES = [];
REQUIRED_ENVIRONMENT_VARIABLES.forEach(function (variableName) {
    if (!process.env[variableName]) {
        MISSING_VARIABLES.push(variableName);
    }
});
if (MISSING_VARIABLES.length > 0) {
    var message = 'Missing environment variables: ' + MISSING_VARIABLES.join(', ');
    console.error(message);
    throw new Error(message);
}

process.env.TZ = 'Europe/Warsaw';

var gith = require('gith').create(process.env.WEBHOOK_LISTENER_GITHUB_WEBHOOK_PORT);
var execFile = require('child_process').execFile;
var nodeSlackr = require('node-slackr');

var slack = new nodeSlackr(process.env.WEBHOOK_LISTENER_SLACK_HOOK_TOKEN);

function sendMessageToSlack(message) {
    var formattedDate = '`' + new Date() + '`\n';
    var messages = {
        text: formattedDate + message,
        channel: '#builds'
    };
    slack.notify(messages, function (err, result) {
        if (!err) {
            console.log('Sent message: ');
            console.log(messages);
        } else {
            console.error('Something went wrong in sending message: ');
            console.error(err);
            console.error(messages);
        }
    });
}

sendMessageToSlack('*Siema Heniu*');

var targets = [
    {
        repo: 'codepotpl/codepot',
        branch: 'production',
        appName: 'WEBSITE PRODUCTION',
        script: './codepot-production.sh'
    },
    {
        repo: 'codepotpl/codepot',
        branch: 'master',
        appName: 'WEBSITE STAGING',
        script: './codepot-staging.sh'
    },
    {
        repo: 'codepotpl/codepot-webclient',
        branch: 'master',
        appName: 'WEBCLIENT STAGING',
        script: './codepot-webclient-staging.sh'
    },
    {
        repo: 'codepotpl/codepot-webclient',
        branch: 'production',
        appName: 'WEBCLIENT PRODUCTION',
        script: './codepot-webclient-production.sh'
    },
    {
        repo: 'codepotpl/codepot-backend',
        branch: 'master',
        appName: 'BACKEND STAGING',
        script: './codepot-backend-staging.sh'
    },
    {
        repo: 'codepotpl/codepot-backend',
        branch: 'production',
        appName: 'BACKEND PRODUCTION',
        script: './codepot-backend-production.sh'
    }
];

targets.forEach(function (target) {
    gith({
        repo: target.repo,
        branch: target.branch
    }).on('all', function (payload) {
        var message = '------ *' + target.repo + ':' + target.branch + '* changed ------\nPusher: `' + payload.pusher + '`.\n\nBuilding and running new ' + target.appName;
        sendMessageToSlack(message);

        var startDate = new Date();
        execFile(target.script, function (error, stdout, stderr) {
            var message;
            if (!error) {
                message = '*' + target.appName + ' build complete! Hooray!*';
            } else {
                message = '*' + target.appName + ' build failed!*.\nMore info below:\n\n```' + error + '```';
                console.error('Something went wrong in ' + target.appName + ' build.');
                console.error(error);
            }
            sendMessageToSlack(target.appName + ' build time: `' + (new Date() - startDate) / 1000.0 + '`.\n' + message);
        });
    });
});<|endoftext|>


<commit_before>const Vec3 = require('vec3').Vec3
const assert = require('assert')
const math = require('../math')
const conv = require('../conversions')
const { performance } = require('perf_hooks')
const { callbackify, createDoneTask, createTask } = require('../promise_utils')

const { Physics, PlayerState } = require('prismarine-physics')

module.exports = inject

const PI = Math.PI
const PI_2 = Math.PI * 2
const PHYSICS_INTERVAL_MS = 50
const PHYSICS_TIMESTEP = PHYSICS_INTERVAL_MS / 1000

function inject (bot) {
  const mcData = require('minecraft-data')(bot.version)

  const world = { getBlock: (pos) => { return bot.blockAt(pos, false) } }
  const physics = Physics(mcData, world)

  bot.jumpQueued = false
  bot.jumpTicks = 0 // autojump cooldown

  const controlState = {
    forward: false,
    back: false,
    left: false,
    right: false,
    jump: false,
    sprint: false,
    sneak: false
  }
  let lastSentYaw = null
  let doPhysicsTimer = null
  let lastPhysicsFrameTime = null
  let physicEnabled = false

  const lastSent = {
    x: 0,
    y: 0,
    z: 0,
    yaw: 0,
    pitch: 0,
    onGround: false,
    time: 0
  }

  // This function should be executed each tick (every 0.05 seconds)
  // How it works: https://gafferongames.com/post/fix_your_timestep/
  let timeAccumulator = 0
  function doPhysics () {
    const now = performance.now()
    const deltaSeconds = (now - lastPhysicsFrameTime) / 1000
    lastPhysicsFrameTime = now

    timeAccumulator += deltaSeconds

    while (timeAccumulator >= PHYSICS_TIMESTEP) {
      if (physicEnabled) {
        physics.simulatePlayer(new PlayerState(bot, controlState), world).apply(bot)
        bot.emit('physicTick')
      }
      updatePosition(PHYSICS_TIMESTEP)
      timeAccumulator -= PHYSICS_TIMESTEP
    }
  }

  function cleanup () {
    clearInterval(doPhysicsTimer)
    doPhysicsTimer = null
  }

  function sendPacketPosition (position, onGround) {
    // sends data, no logic
    const oldPos = new Vec3(lastSent.x, lastSent.y, lastSent.z)
    lastSent.x = position.x
    lastSent.y = position.y
    lastSent.z = position.z
    lastSent.onGround = onGround
    bot._client.write('position', lastSent)
    bot.emit('move', oldPos)
  }

  function sendPacketLook (yaw, pitch, onGround) {
    // sends data, no logic
    const oldPos = new Vec3(lastSent.x, lastSent.y, lastSent.z)
    lastSent.yaw = yaw
    lastSent.pitch = pitch
    lastSent.onGround = onGround
    bot._client.write('look', lastSent)
    bot.emit('move', oldPos)
  }

  function sendPacketPositionAndLook (position, yaw, pitch, onGround) {
    // sends data, no logic
    const oldPos = new Vec3(lastSent.x, lastSent.y, lastSent.z)
    lastSent.x = position.x
    lastSent.y = position.y
    lastSent.z = position.z
    lastSent.yaw = yaw
    lastSent.pitch = pitch
    lastSent.onGround = onGround
    bot._client.write('position_look', lastSent)
    bot.emit('move', oldPos)
  }

  function deltaYaw (yaw1, yaw2) {
    let dYaw = (yaw1 - yaw2) % PI_2
    if (dYaw < -PI) dYaw += PI_2
    else if (dYaw > PI) dYaw -= PI_2

    return dYaw
  }

  function updatePosition (dt) {
    // If you're dead, you're probably on the ground though ...
    if (!bot.isAlive) bot.entity.onGround = true

    // Increment the yaw in baby steps so that notchian clients (not the server) can keep up.
    const dYaw = deltaYaw(bot.entity.yaw, lastSentYaw)

    // Vanilla doesn't clamp yaw, so we don't want to do it either
    const maxDeltaYaw = dt * physics.yawSpeed
    lastSentYaw += math.clamp(-maxDeltaYaw, dYaw, maxDeltaYaw)

    const yaw = conv.toNotchianYaw(lastSentYaw)
    const pitch = conv.toNotchianPitch(bot.entity.pitch)
    const position = bot.entity.position
    const onGround = bot.entity.onGround

    // Only send a position update if necessary, select the appropriate packet
    const positionUpdated = lastSent.x !== position.x || lastSent.y !== position.y || lastSent.z !== position.z
    const lookUpdated = lastSent.yaw !== yaw || lastSent.pitch !== pitch

    if (positionUpdated && lookUpdated && bot.isAlive) {
      sendPacketPositionAndLook(position, yaw, pitch, onGround)
    } else if (positionUpdated && bot.isAlive) {
      sendPacketPosition(position, onGround)
    } else if (lookUpdated && bot.isAlive) {
      sendPacketLook(yaw, pitch, onGround)
    } else if (performance.now() - lastSent.time >= 1000) {
      // Send a position packet every second, even if no update was made
      sendPacketPosition(position, onGround)
      lastSent.time = performance.now()
    } else if (bot.supportFeature('positionUpdateSentEveryTick') && bot.isAlive) {
      // For versions < 1.12, one player packet should be sent every tick
      // for the server to update health correctly
      bot._client.write('flying', { onGround: bot.entity.onGround })
    }
  }

  bot.physics = physics

  bot.setControlState = (control, state) => {
    assert.ok(control in controlState, `invalid control: ${control}`)
    assert.ok(typeof state === 'boolean', `invalid state: ${state}`)
    if (controlState[control] === state) return
    controlState[control] = state
    if (control === 'jump' && state) {
      bot.jumpQueued = true
    } else if (control === 'sprint') {
      bot._client.write('entity_action', {
        entityId: bot.entity.id,
        actionId: state ? 3 : 4,
        jumpBoost: 0
      })
    } else if (control === 'sneak') {
      bot._client.write('entity_action', {
        entityId: bot.entity.id,
        actionId: state ? 0 : 1,
        jumpBoost: 0
      })
    }
  }

  bot.clearControlStates = () => {
    for (const control in controlState) {
      bot.setControlState(control, false)
    }
  }

  bot.controlState = {}

  for (const control of Object.keys(controlState)) {
    Object.defineProperty(bot.controlState, control, {
      get () {
        return controlState[control]
      },
      set (state) {
        bot.setControlState(control, state)
        return state
      }
    })
  }

  let lookingTask = createDoneTask()

  bot.on('move', () => {
    if (!lookingTask.done && Math.abs(deltaYaw(bot.entity.yaw, lastSentYaw)) < 0.001) {
      lookingTask.finish()
    }
  })

  bot.look = callbackify(async (yaw, pitch, force) => {
    if (!lookingTask.done) {
      lookingTask.finish() // finish the previous one
    }
    lookingTask = createTask()

    bot.entity.yaw = yaw
    bot.entity.pitch = pitch
    if (force) {
      lastSentYaw = yaw
      return
    }

    await lookingTask.promise
  })

  bot.lookAt = callbackify(async (point, force) => {
    const delta = point.minus(bot.entity.position.offset(0, bot.entity.height, 0))
    const yaw = Math.atan2(-delta.x, -delta.z)
    const groundDistance = Math.sqrt(delta.x * delta.x + delta.z * delta.z)
    const pitch = Math.atan2(delta.y, groundDistance)
    await bot.look(yaw, pitch, force)
  })

  // player position and look (clientbound)
  bot._client.on('position', (packet) => {
    bot.entity.height = 1.62
    bot.entity.velocity.set(0, 0, 0)

    // If flag is set, then the corresponding value is relative, else it is absolute
    const pos = bot.entity.position
    pos.set(
      packet.flags & 1 ? (pos.x + packet.x) : packet.x,
      packet.flags & 2 ? (pos.y + packet.y) : packet.y,
      packet.flags & 4 ? (pos.z + packet.z) : packet.z
    )

    const newYaw = (packet.flags & 8 ? conv.toNotchianYaw(bot.entity.yaw) : 0) + packet.yaw
    const newPitch = (packet.flags & 16 ? conv.toNotchianPitch(bot.entity.pitch) : 0) + packet.pitch
    bot.entity.yaw = conv.fromNotchianYaw(newYaw)
    bot.entity.pitch = conv.fromNotchianPitch(newPitch)
    bot.entity.onGround = false

    if (bot.supportFeature('teleportUsesOwnPacket')) {
      bot._client.write('teleport_confirm', { teleportId: packet.teleportId })
      // Force send an extra packet to be like vanilla client
      sendPacketPositionAndLook(pos, newYaw, newPitch, bot.entity.onGround)
    }
    sendPacketPositionAndLook(pos, newYaw, newPitch, bot.entity.onGround)

    physicEnabled = true
    bot.entity.timeSinceOnGround = 0
    lastSentYaw = bot.entity.yaw

    if (doPhysicsTimer === null) {
      lastPhysicsFrameTime = performance.now()
      doPhysicsTimer = setInterval(doPhysics, PHYSICS_INTERVAL_MS)
    }
    bot.emit('forcedMove')
  })

  bot.waitForTicks = async function (ticks) {
    if (ticks <= 0) return
    await new Promise(resolve => {
      const tickListener = () => {
        ticks--
        if (ticks === 0) {
          this.bot.removeListener('physicTick', tickListener)
          resolve()
        }
      }

      this.bot.on('physicTick', tickListener)
    })
  }

  bot.on('mount', () => { physicEnabled = false })
  bot.on('respawn', () => { physicEnabled = false })
  bot.on('end', cleanup)
}
<commit_msg>Removed broken use of "this" (#1620)<commit_after>const Vec3 = require('vec3').Vec3
const assert = require('assert')
const math = require('../math')
const conv = require('../conversions')
const { performance } = require('perf_hooks')
const { callbackify, createDoneTask, createTask } = require('../promise_utils')

const { Physics, PlayerState } = require('prismarine-physics')

module.exports = inject

const PI = Math.PI
const PI_2 = Math.PI * 2
const PHYSICS_INTERVAL_MS = 50
const PHYSICS_TIMESTEP = PHYSICS_INTERVAL_MS / 1000

function inject (bot) {
  const mcData = require('minecraft-data')(bot.version)

  const world = { getBlock: (pos) => { return bot.blockAt(pos, false) } }
  const physics = Physics(mcData, world)

  bot.jumpQueued = false
  bot.jumpTicks = 0 // autojump cooldown

  const controlState = {
    forward: false,
    back: false,
    left: false,
    right: false,
    jump: false,
    sprint: false,
    sneak: false
  }
  let lastSentYaw = null
  let doPhysicsTimer = null
  let lastPhysicsFrameTime = null
  let physicEnabled = false

  const lastSent = {
    x: 0,
    y: 0,
    z: 0,
    yaw: 0,
    pitch: 0,
    onGround: false,
    time: 0
  }

  // This function should be executed each tick (every 0.05 seconds)
  // How it works: https://gafferongames.com/post/fix_your_timestep/
  let timeAccumulator = 0
  function doPhysics () {
    const now = performance.now()
    const deltaSeconds = (now - lastPhysicsFrameTime) / 1000
    lastPhysicsFrameTime = now

    timeAccumulator += deltaSeconds

    while (timeAccumulator >= PHYSICS_TIMESTEP) {
      if (physicEnabled) {
        physics.simulatePlayer(new PlayerState(bot, controlState), world).apply(bot)
        bot.emit('physicTick')
      }
      updatePosition(PHYSICS_TIMESTEP)
      timeAccumulator -= PHYSICS_TIMESTEP
    }
  }

  function cleanup () {
    clearInterval(doPhysicsTimer)
    doPhysicsTimer = null
  }

  function sendPacketPosition (position, onGround) {
    // sends data, no logic
    const oldPos = new Vec3(lastSent.x, lastSent.y, lastSent.z)
    lastSent.x = position.x
    lastSent.y = position.y
    lastSent.z = position.z
    lastSent.onGround = onGround
    bot._client.write('position', lastSent)
    bot.emit('move', oldPos)
  }

  function sendPacketLook (yaw, pitch, onGround) {
    // sends data, no logic
    const oldPos = new Vec3(lastSent.x, lastSent.y, lastSent.z)
    lastSent.yaw = yaw
    lastSent.pitch = pitch
    lastSent.onGround = onGround
    bot._client.write('look', lastSent)
    bot.emit('move', oldPos)
  }

  function sendPacketPositionAndLook (position, yaw, pitch, onGround) {
    // sends data, no logic
    const oldPos = new Vec3(lastSent.x, lastSent.y, lastSent.z)
    lastSent.x = position.x
    lastSent.y = position.y
    lastSent.z = position.z
    lastSent.yaw = yaw
    lastSent.pitch = pitch
    lastSent.onGround = onGround
    bot._client.write('position_look', lastSent)
    bot.emit('move', oldPos)
  }

  function deltaYaw (yaw1, yaw2) {
    let dYaw = (yaw1 - yaw2) % PI_2
    if (dYaw < -PI) dYaw += PI_2
    else if (dYaw > PI) dYaw -= PI_2

    return dYaw
  }

  function updatePosition (dt) {
    // If you're dead, you're probably on the ground though ...
    if (!bot.isAlive) bot.entity.onGround = true

    // Increment the yaw in baby steps so that notchian clients (not the server) can keep up.
    const dYaw = deltaYaw(bot.entity.yaw, lastSentYaw)

    // Vanilla doesn't clamp yaw, so we don't want to do it either
    const maxDeltaYaw = dt * physics.yawSpeed
    lastSentYaw += math.clamp(-maxDeltaYaw, dYaw, maxDeltaYaw)

    const yaw = conv.toNotchianYaw(lastSentYaw)
    const pitch = conv.toNotchianPitch(bot.entity.pitch)
    const position = bot.entity.position
    const onGround = bot.entity.onGround

    // Only send a position update if necessary, select the appropriate packet
    const positionUpdated = lastSent.x !== position.x || lastSent.y !== position.y || lastSent.z !== position.z
    const lookUpdated = lastSent.yaw !== yaw || lastSent.pitch !== pitch

    if (positionUpdated && lookUpdated && bot.isAlive) {
      sendPacketPositionAndLook(position, yaw, pitch, onGround)
    } else if (positionUpdated && bot.isAlive) {
      sendPacketPosition(position, onGround)
    } else if (lookUpdated && bot.isAlive) {
      sendPacketLook(yaw, pitch, onGround)
    } else if (performance.now() - lastSent.time >= 1000) {
      // Send a position packet every second, even if no update was made
      sendPacketPosition(position, onGround)
      lastSent.time = performance.now()
    } else if (bot.supportFeature('positionUpdateSentEveryTick') && bot.isAlive) {
      // For versions < 1.12, one player packet should be sent every tick
      // for the server to update health correctly
      bot._client.write('flying', { onGround: bot.entity.onGround })
    }
  }

  bot.physics = physics

  bot.setControlState = (control, state) => {
    assert.ok(control in controlState, `invalid control: ${control}`)
    assert.ok(typeof state === 'boolean', `invalid state: ${state}`)
    if (controlState[control] === state) return
    controlState[control] = state
    if (control === 'jump' && state) {
      bot.jumpQueued = true
    } else if (control === 'sprint') {
      bot._client.write('entity_action', {
        entityId: bot.entity.id,
        actionId: state ? 3 : 4,
        jumpBoost: 0
      })
    } else if (control === 'sneak') {
      bot._client.write('entity_action', {
        entityId: bot.entity.id,
        actionId: state ? 0 : 1,
        jumpBoost: 0
      })
    }
  }

  bot.clearControlStates = () => {
    for (const control in controlState) {
      bot.setControlState(control, false)
    }
  }

  bot.controlState = {}

  for (const control of Object.keys(controlState)) {
    Object.defineProperty(bot.controlState, control, {
      get () {
        return controlState[control]
      },
      set (state) {
        bot.setControlState(control, state)
        return state
      }
    })
  }

  let lookingTask = createDoneTask()

  bot.on('move', () => {
    if (!lookingTask.done && Math.abs(deltaYaw(bot.entity.yaw, lastSentYaw)) < 0.001) {
      lookingTask.finish()
    }
  })

  bot.look = callbackify(async (yaw, pitch, force) => {
    if (!lookingTask.done) {
      lookingTask.finish() // finish the previous one
    }
    lookingTask = createTask()

    bot.entity.yaw = yaw
    bot.entity.pitch = pitch
    if (force) {
      lastSentYaw = yaw
      return
    }

    await lookingTask.promise
  })

  bot.lookAt = callbackify(async (point, force) => {
    const delta = point.minus(bot.entity.position.offset(0, bot.entity.height, 0))
    const yaw = Math.atan2(-delta.x, -delta.z)
    const groundDistance = Math.sqrt(delta.x * delta.x + delta.z * delta.z)
    const pitch = Math.atan2(delta.y, groundDistance)
    await bot.look(yaw, pitch, force)
  })

  // player position and look (clientbound)
  bot._client.on('position', (packet) => {
    bot.entity.height = 1.62
    bot.entity.velocity.set(0, 0, 0)

    // If flag is set, then the corresponding value is relative, else it is absolute
    const pos = bot.entity.position
    pos.set(
      packet.flags & 1 ? (pos.x + packet.x) : packet.x,
      packet.flags & 2 ? (pos.y + packet.y) : packet.y,
      packet.flags & 4 ? (pos.z + packet.z) : packet.z
    )

    const newYaw = (packet.flags & 8 ? conv.toNotchianYaw(bot.entity.yaw) : 0) + packet.yaw
    const newPitch = (packet.flags & 16 ? conv.toNotchianPitch(bot.entity.pitch) : 0) + packet.pitch
    bot.entity.yaw = conv.fromNotchianYaw(newYaw)
    bot.entity.pitch = conv.fromNotchianPitch(newPitch)
    bot.entity.onGround = false

    if (bot.supportFeature('teleportUsesOwnPacket')) {
      bot._client.write('teleport_confirm', { teleportId: packet.teleportId })
      // Force send an extra packet to be like vanilla client
      sendPacketPositionAndLook(pos, newYaw, newPitch, bot.entity.onGround)
    }
    sendPacketPositionAndLook(pos, newYaw, newPitch, bot.entity.onGround)

    physicEnabled = true
    bot.entity.timeSinceOnGround = 0
    lastSentYaw = bot.entity.yaw

    if (doPhysicsTimer === null) {
      lastPhysicsFrameTime = performance.now()
      doPhysicsTimer = setInterval(doPhysics, PHYSICS_INTERVAL_MS)
    }
    bot.emit('forcedMove')
  })

  bot.waitForTicks = async function (ticks) {
    if (ticks <= 0) return
    await new Promise(resolve => {
      const tickListener = () => {
        ticks--
        if (ticks === 0) {
          bot.removeListener('physicTick', tickListener)
          resolve()
        }
      }

      this.bot.on('physicTick', tickListener)
    })
  }

  bot.on('mount', () => { physicEnabled = false })
  bot.on('respawn', () => { physicEnabled = false })
  bot.on('end', cleanup)
}
<|endoftext|>