<commit_before>

// IMPORT
// =============================================================================
require('./globals')
import Koa from 'koa'
import session from 'koa-session'
import router from 'koa-router')(
const app = new Koa()
require('koa-qs')(app)
import koaBody from 'koa-body'
import TrafficControl from './TrafficControl'
import render from 'koa-ejs'
import path from 'path'
import http from 'http'
import ws from 'ws'
import { URL } from 'url'
import logger from './logger'
import { promisify } from 'util'
const {
  APIError,
  InternalServerError,
  TooManyRequestsAPIError,
  BadRequestAPIError
} = require('./APIError')

import Permission from './permission'
import uid from 'uid-safe'
import npid from 'npid'

// Import config
import config from '../../config'

// Import controllers
import Authentication from './controllers/auth'
const client = new (require('./controllers/client'))()
const decal = new (require('./controllers/decal'))()
const login = new (require('./controllers/login'))()
const nicknames = new (require('./controllers/nicknames'))()
import oauth2 from './controllers/oauth2'
const profile = new (require('./controllers/profile'))()
const rat = new (require('./controllers/rat'))()
const register = new (require('./controllers/register'))()
const reset = new (require('./controllers/reset'))()
const rescue = new (require('./controllers/rescue'))()
const ship = new (require('./controllers/ship'))()
const statistics = new (require('./controllers/statistics'))()
const user = new (require('./controllers/user'))()
const version = new (require('./controllers/version'))()
import WebSocketManager from './websocket'
import jiraDrill from './controllers/jira/drill'
import { AnopeWebhook } from './controllers/anope-webhook'
import { db } from './db/index'

try {
  npid.remove('api.pid')
  let pid = npid.create('api.pid')
  pid.removeOnExit()
} catch (err) {
  process.exit(1)
}

app.keys = [config.cookie.secret]

let sessionConfiguration = {
  key: 'fuelrats:session',
  overwrite: true,
  signed: true
}

app.use(session(sessionConfiguration, app))
app.use(require('koa-static')('static', {
  hidden: false,
  gzip: true
}))
app.use(koaBody())

let port = config.port || process.env.PORT

app.use(async function (ctx, next) {
  ctx.data = ctx.request.body
  ctx.meta = WebSocketManager.meta
  ctx.client = {}

  let { query } = ctx
  ctx.query = parseQuery(query)

  if (ctx.request.headers['x-forwarded-for']) {
    [ctx.inet] = ctx.request.headers['x-forwarded-for'].split(', ')
  } else {
    ctx.inet =  ctx.request.ip
  }

  await next()
})

app.use(async function (ctx, next) {
  if (Array.isArray(ctx.data) || typeof ctx.data === 'object') {
    ['id', 'createdAt', 'updatedAt', 'deletedAt'].map((cleanField) => {
      delete ctx.data[cleanField]
    })
  }
  await next()
})

const traffic = new TrafficControl()

app.use(async (ctx, next) => {
  try {
    await Authentication.authenticate(ctx)

    let rateLimit = traffic.validateRateLimit(ctx)

    ctx.set('X-API-Version', '2.0')
    ctx.set('X-Rate-Limit-Limit', rateLimit.total)
    ctx.set('X-Rate-Limit-Remaining', rateLimit.remaining)
    ctx.set('X-Rate-Limit-Reset', rateLimit.nextResetDate)

    logger.info({ tags: ['request'] }, `Request by ${ctx.inet} to ${ctx.request.path}`, {
      'ip': ctx.inet,
      'path': ctx.request.path,
      'rate-limit-limit': rateLimit.total,
      'rate-limit-remaining': rateLimit.remaining,
      'query': ctx.query,
      'body': censor(ctx.data),
      'method': ctx.request.req.method
    })

    if (rateLimit.exceeded) {
      return next(new TooManyRequestsAPIError({}))
    }

    let result = await next()
    if (result === true) {
      ctx.status = 204
    } else if (result) {
      ctx.body = result
    }
  } catch (ex) {
    let error = ex

    if ((error instanceof APIError) === false) {
      error = new InternalServerError({})
    }
    ctx.status = error.code
    ctx.body = {
      errors: [error]
    }
  }
})

render(app, {
  root: path.join(__dirname, 'views'),
  layout: false,
  viewExt: 'html',
  cache: false,
  debug: true
})

// ROUTES
// =============================================================================

// RESCUES
router.get('/rescues',
  Authentication.isAuthenticated,
  Permission.required(['rescue.read']),
  rescue.search)

router.get('/rescues/:id',
  Authentication.isAuthenticated,
  Permission.required(['rescue.read']),
  params('id'),
  rescue.findById)

router.post('/rescues',
  Authentication.isAuthenticated,
  Permission.required(['rescue.write']),
  rescue.create)

router.put('/rescues/:id',
  Authentication.isAuthenticated,
  params('id'),
  rescue.update)

router.put('/rescues/assign/:id',
  Authentication.isAuthenticated,
  params('id'),
  rescue.assign)

router.put('/rescues/addquote/:id',
  Authentication.isAuthenticated,
  params('id'),
  rescue.assign)

router.put('/rescues/unassign/:id',
  Authentication.isAuthenticated,
  params('id'),
  rescue.unassign)

router.delete('/rescues/:id',
  Authentication.isAuthenticated,
  Permission.required(['rescue.delete']),
  params('id'),
  rescue.delete)

// CLIENTS
router.get('/clients',
  Authentication.isAuthenticated,
  Permission.required(['client.read']),
  client.search)

router.get('/clients/:id',
  Authentication.isAuthenticated,
  params('id'),
  client.findById)

router.post('/clients',
  Authentication.isAuthenticated,
  client.create)

router.put('/clients/:id',
  Authentication.isAuthenticated,
  params('id'),
  client.update)

router.delete('/clients/:id',
  Authentication.isAuthenticated,
  Permission.required(['client.delete']),
  params('id'),
  client.delete)

// USERS
router.get('/users',
  Authentication.isAuthenticated,
  Permission.required(['user.read']),
  user.search)

router.get('/users/:id',
  Authentication.isAuthenticated,
  params('id'),
  user.findById)

router.get('/users/image/:id',
  params('id'),
  user.image)

router.post('/users',
  Authentication.isAuthenticated,
  user.create)

router.put('/users/setpassword',
  Authentication.isAuthenticated,
  fields('password', 'new'),
  user.setpassword)

router.post('/users/image/:id',
  Authentication.isAuthenticated,
  user.setimage)
router.put('/users/:id/updatevirtualhost',
  Authentication.isAuthenticated,
  Permission.required(['user.write']),
  params('id'),
  user.updatevirtualhost)

router.put('/users/:id',
  clean('image', 'password'),
  Authentication.isAuthenticated,
  params('id'),
  user.update)

router.delete('/users/:id',
  Authentication.isAuthenticated,
  Permission.required(['user.delete']),
  params('id'),
  user.delete)

router.get('/nicknames/info/:nickname',
  Authentication.isAuthenticated,
  params('nickname'),
  nicknames.info)

router.get('/nicknames/:nickname',
  Authentication.isAuthenticated,
  params('nickname'),
  nicknames.search)

router.post('/nicknames',
  Authentication.isAuthenticated,
  nicknames.register)

router.put('/nicknames',
  Authentication.isAuthenticated,
  nicknames.connect)

router.delete('/nicknames/:nickname',
  Authentication.isAuthenticated,
  params('nickname'),
  nicknames.delete)

// RATS
router.get('/rats',
  rat.search)

router.get('/rats/:id',
  params('id'),
  rat.findById)

router.post('/rats',
  rat.create)

router.put('/rats/:id',
  params('id'),
  rat.update)

router.delete('/rats/:id',
  Permission.required(['rat.delete']),
  params('id'),
  rat.delete)

// SHIPS
router.get('/ships',
  ship.search)

router.get('/ships/:id',
  params('id'),
  ship.findById)

router.post('/ships',
  fields('name', 'shipType', 'ratId'),
  clean('shipId'),
  ship.create)

router.put('/ships/:id',
  clean('shipId'),
  params('id'),
  ship.update)

router.delete('/ships/:id',
  params('id'),
  rat.delete)

// WELCOME
router.get('/welcome', (ctx) => {
  ctx.redirect('https://fuelrats.com/profile')
  ctx.status = 301
})

// LOGIN
router.post('/login',
  fields('email', 'password'),
  login.login)

// REGISTER
router.post('/register',
  fields('email', 'password', 'name', 'platform', 'nickname'),
  register.create)

// PROFILE
router.get('/profile',
  Authentication.isAuthenticated, Permission.required(['user.read.me']),
  profile.read)

// ANOPE
router.post('/anope',
  Authentication.isWhitelisted,
  AnopeWebhook.update)

// OAUTH2
router.get('/oauth2/authorize',
  Authentication.isAuthenticated,
  oauth2.authorizationValidateRedirect,
  oauth2.authorizationRender
)

router.post('/oauth2/authorize',
  Authentication.isAuthenticated,
  ...oauth2.server.decision())

router.post('/oauth2/token',
  Authentication.isClientAuthenticated,
  oauth2.server.token(),
  oauth2.server.errorHandler())

router.post('/oauth2/revoke',
  Authentication.isClientAuthenticated,
  oauth2.revoke)
router.post('/oauth2/revokeall',
  Authentication.isClientAuthenticated,
  oauth2.revokeAll)

// STATISTICS
router.get('/statistics/rescues',
  statistics.rescues)

router.get('/statistics/systems',
  statistics.systems)

router.get('/statistics/rats',
  statistics.rats)

// VERSION
router.get('/version', version.read)

// RESET
router.post('/reset',
  fields('email'),
  reset.requestReset)

router.get('/reset/:token',
  params('token'),
  reset.validateReset)

router.post('/reset/:token',
  params('token'),
  fields('password'),
  reset.resetPassword)

// DECALS
router.get('/decals/check',
  Authentication.isAuthenticated,
  decal.check)

router.get('/decals/redeem',
  Authentication.isAuthenticated,
  decal.redeem)

// JIRA
router.post('/jira/drill',
  Authentication.isAuthenticated,
  Permission.required(['user.write']),
  jiraDrill.update)

app.use(router.routes())
app.use(router.allowedMethods())

/**
 * Parses an object of URL query parameters and builds a nested object by delimiting periods into sub objects.
 * @param query an array of URL query parameters
 * @returns {{}} a nested object
 */
function parseQuery (query) {
  let queryObj = {}

  // Iterate over each individual query item
  for (let key of Object.keys(query)) {
    // Split them into period delimited arrays
    let keys = key.split('.')
    let target = queryObj

    // Iterate over the period delimited arrays to construct a nested hierarchy
    for (let keyPair of keys.entries()) {
      let [, subkey ] = keyPair
      if (keyPair[0] === keys.length - 1) {
        // We have reached the end of the delimited array which means we can insert the value

        target[subkey] = query[key]
      } else if (!target[subkey]) {
        /* We have not reached the end of the delimited array so we need to create a nested object unless
        it already exists */
        target[subkey] = {}
        target = target[subkey]
      }
    }
  }
  return queryObj
}

let server = http.createServer(app.callback())
const wss = new ws.Server({ server })

const websocketManager = new WebSocketManager(wss, traffic)

wss.on('connection', async function connection (client, req) {
  let url = new URL(`http://localhost:8082${req.url}`)
  client.req = req
  client.clientId = uid.sync(GLOBAL.WEBSOCKET_IDENTIFIER_ROUNDS)
  client.subscriptions = []

  let bearer = url.searchParams.get('bearer')
  if (bearer) {
    let { user, scope } = await Authentication.bearerAuthenticate(bearer)
    if (user) {
      client.user = user
      client.scope = scope
    }
  }

  websocketManager.onConnection(client)

  client.on('message', (message) => {
    client.websocket = wss
    try {
      let request = JSON.parse(message)
      websocketManager.onMessage(client, request)
    } catch (ex) {
      logger.info('Failed to parse incoming websocket message')
    }
  })
})

/**
 * Goes through an object and sets properties commonly usde to hold sensitive information to a static value.
 * @param obj The object to censor
 * @returns {{}} A censored object
 */
function censor (obj) {
  let censoredObj = {}
  Object.assign(censoredObj, obj)

  if (censoredObj.password) {
    censoredObj.password = '[CENSORED]'
  }
  if (censoredObj.secret) {
    censoredObj.secret = '[CENSORED]'
  }

  return censoredObj
}

/**
 * Makes sure the request object has the required data fields specified
 * @param requiredFields The data fields to require
 * @returns {Function} A promise
 */
function fields (...requiredFields) {
  return function (ctx, next) {
    let missingFields = requiredFields.filter((requiredField) => {
      return ctx.data.hasOwnProperty(requiredField) === false
    })
    if (missingFields.length > 0) {
      throw missingFields.map((field) => {
        return new BadRequestAPIError({ pointer: `/data/attributes/${field}` })
      })
    }
    return next()
  }
}

/**
 * Makes sure the request object has the required params specified
 * @param requiredFields The data fields to require
 * @returns {Function} A promise
 */
function params (...requiredFields) {
  return function (ctx, next) {
    let missingFields = requiredFields.filter((requiredField) => {
      return ctx.query.hasOwnProperty(requiredField) === false
    })
    if (missingFields.length > 0) {
      throw missingFields.map((field) => {
        return new BadRequestAPIError({ parameter: field })
      })
    }
    return next()
  }
}

/**
 * Removes the specified data fields from the request object
 * @param cleanFields The data fields to clean away
 * @returns {Function} A promise
 */
function clean (...cleanFields) {
  return function (ctx, next) {
    if (Array.isArray(ctx.data) || typeof ctx.data === 'object') {
      cleanFields.map((cleanField) => {
        ctx.data[cleanField] = undefined
      })
    }
    return next()
  }
}

(async function startServer () {
  try {
    await db.sync()
    const listen = promisify(server.listen.bind(server))
    await listen(port, config.hostname)
    logger.info(`HTTP Server listening on ${config.hostname} port ${port}`)
  } catch (error) {
    logger.error(error)
  }
})()

// allow launch of app from unit tests
module.exports = server<commit_msg>Fix more invalid import syntax nonsense<commit_after>

// IMPORT
// =============================================================================
require('./globals')
import Koa from 'koa'
import session from 'koa-session'
import Router from 'koa-router'
const app = new Koa()
import querystring from 'koa-qs'
querystring(app)
import koaBody from 'koa-body'
import TrafficControl from './TrafficControl'
import render from 'koa-ejs'
import path from 'path'
import http from 'http'
import ws from 'ws'
import { URL } from 'url'
import logger from './logger'
import { promisify } from 'util'
const {
  APIError,
  InternalServerError,
  TooManyRequestsAPIError,
  BadRequestAPIError
} = require('./APIError')

import Permission from './permission'
import uid from 'uid-safe'
import npid from 'npid'

let router = Router()

// Import config
import config from '../../config'

// Import controllers
import Authentication from './controllers/auth'
const client = new (require('./controllers/client'))()
const decal = new (require('./controllers/decal'))()
const login = new (require('./controllers/login'))()
const nicknames = new (require('./controllers/nicknames'))()
import oauth2 from './controllers/oauth2'
const profile = new (require('./controllers/profile'))()
const rat = new (require('./controllers/rat'))()
const register = new (require('./controllers/register'))()
const reset = new (require('./controllers/reset'))()
const rescue = new (require('./controllers/rescue'))()
const ship = new (require('./controllers/ship'))()
const statistics = new (require('./controllers/statistics'))()
const user = new (require('./controllers/user'))()
const version = new (require('./controllers/version'))()
import WebSocketManager from './websocket'
import jiraDrill from './controllers/jira/drill'
import { AnopeWebhook } from './controllers/anope-webhook'
import { db } from './db/index'

try {
  npid.remove('api.pid')
  let pid = npid.create('api.pid')
  pid.removeOnExit()
} catch (err) {
  process.exit(1)
}

app.keys = [config.cookie.secret]

let sessionConfiguration = {
  key: 'fuelrats:session',
  overwrite: true,
  signed: true
}

app.use(session(sessionConfiguration, app))
app.use(require('koa-static')('static', {
  hidden: false,
  gzip: true
}))
app.use(koaBody())

let port = config.port || process.env.PORT

app.use(async function (ctx, next) {
  ctx.data = ctx.request.body
  ctx.meta = WebSocketManager.meta
  ctx.client = {}

  let { query } = ctx
  ctx.query = parseQuery(query)

  if (ctx.request.headers['x-forwarded-for']) {
    [ctx.inet] = ctx.request.headers['x-forwarded-for'].split(', ')
  } else {
    ctx.inet =  ctx.request.ip
  }

  await next()
})

app.use(async function (ctx, next) {
  if (Array.isArray(ctx.data) || typeof ctx.data === 'object') {
    ['id', 'createdAt', 'updatedAt', 'deletedAt'].map((cleanField) => {
      delete ctx.data[cleanField]
    })
  }
  await next()
})

const traffic = new TrafficControl()

app.use(async (ctx, next) => {
  try {
    await Authentication.authenticate(ctx)

    let rateLimit = traffic.validateRateLimit(ctx)

    ctx.set('X-API-Version', '2.0')
    ctx.set('X-Rate-Limit-Limit', rateLimit.total)
    ctx.set('X-Rate-Limit-Remaining', rateLimit.remaining)
    ctx.set('X-Rate-Limit-Reset', rateLimit.nextResetDate)

    logger.info({ tags: ['request'] }, `Request by ${ctx.inet} to ${ctx.request.path}`, {
      'ip': ctx.inet,
      'path': ctx.request.path,
      'rate-limit-limit': rateLimit.total,
      'rate-limit-remaining': rateLimit.remaining,
      'query': ctx.query,
      'body': censor(ctx.data),
      'method': ctx.request.req.method
    })

    if (rateLimit.exceeded) {
      return next(new TooManyRequestsAPIError({}))
    }

    let result = await next()
    if (result === true) {
      ctx.status = 204
    } else if (result) {
      ctx.body = result
    }
  } catch (ex) {
    let error = ex

    if ((error instanceof APIError) === false) {
      error = new InternalServerError({})
    }
    ctx.status = error.code
    ctx.body = {
      errors: [error]
    }
  }
})

render(app, {
  root: path.join(__dirname, 'views'),
  layout: false,
  viewExt: 'html',
  cache: false,
  debug: true
})

// ROUTES
// =============================================================================

// RESCUES
router.get('/rescues',
  Authentication.isAuthenticated,
  Permission.required(['rescue.read']),
  rescue.search)

router.get('/rescues/:id',
  Authentication.isAuthenticated,
  Permission.required(['rescue.read']),
  params('id'),
  rescue.findById)

router.post('/rescues',
  Authentication.isAuthenticated,
  Permission.required(['rescue.write']),
  rescue.create)

router.put('/rescues/:id',
  Authentication.isAuthenticated,
  params('id'),
  rescue.update)

router.put('/rescues/assign/:id',
  Authentication.isAuthenticated,
  params('id'),
  rescue.assign)

router.put('/rescues/addquote/:id',
  Authentication.isAuthenticated,
  params('id'),
  rescue.assign)

router.put('/rescues/unassign/:id',
  Authentication.isAuthenticated,
  params('id'),
  rescue.unassign)

router.delete('/rescues/:id',
  Authentication.isAuthenticated,
  Permission.required(['rescue.delete']),
  params('id'),
  rescue.delete)

// CLIENTS
router.get('/clients',
  Authentication.isAuthenticated,
  Permission.required(['client.read']),
  client.search)

router.get('/clients/:id',
  Authentication.isAuthenticated,
  params('id'),
  client.findById)

router.post('/clients',
  Authentication.isAuthenticated,
  client.create)

router.put('/clients/:id',
  Authentication.isAuthenticated,
  params('id'),
  client.update)

router.delete('/clients/:id',
  Authentication.isAuthenticated,
  Permission.required(['client.delete']),
  params('id'),
  client.delete)

// USERS
router.get('/users',
  Authentication.isAuthenticated,
  Permission.required(['user.read']),
  user.search)

router.get('/users/:id',
  Authentication.isAuthenticated,
  params('id'),
  user.findById)

router.get('/users/image/:id',
  params('id'),
  user.image)

router.post('/users',
  Authentication.isAuthenticated,
  user.create)

router.put('/users/setpassword',
  Authentication.isAuthenticated,
  fields('password', 'new'),
  user.setpassword)

router.post('/users/image/:id',
  Authentication.isAuthenticated,
  user.setimage)
router.put('/users/:id/updatevirtualhost',
  Authentication.isAuthenticated,
  Permission.required(['user.write']),
  params('id'),
  user.updatevirtualhost)

router.put('/users/:id',
  clean('image', 'password'),
  Authentication.isAuthenticated,
  params('id'),
  user.update)

router.delete('/users/:id',
  Authentication.isAuthenticated,
  Permission.required(['user.delete']),
  params('id'),
  user.delete)

router.get('/nicknames/info/:nickname',
  Authentication.isAuthenticated,
  params('nickname'),
  nicknames.info)

router.get('/nicknames/:nickname',
  Authentication.isAuthenticated,
  params('nickname'),
  nicknames.search)

router.post('/nicknames',
  Authentication.isAuthenticated,
  nicknames.register)

router.put('/nicknames',
  Authentication.isAuthenticated,
  nicknames.connect)

router.delete('/nicknames/:nickname',
  Authentication.isAuthenticated,
  params('nickname'),
  nicknames.delete)

// RATS
router.get('/rats',
  rat.search)

router.get('/rats/:id',
  params('id'),
  rat.findById)

router.post('/rats',
  rat.create)

router.put('/rats/:id',
  params('id'),
  rat.update)

router.delete('/rats/:id',
  Permission.required(['rat.delete']),
  params('id'),
  rat.delete)

// SHIPS
router.get('/ships',
  ship.search)

router.get('/ships/:id',
  params('id'),
  ship.findById)

router.post('/ships',
  fields('name', 'shipType', 'ratId'),
  clean('shipId'),
  ship.create)

router.put('/ships/:id',
  clean('shipId'),
  params('id'),
  ship.update)

router.delete('/ships/:id',
  params('id'),
  rat.delete)

// WELCOME
router.get('/welcome', (ctx) => {
  ctx.redirect('https://fuelrats.com/profile')
  ctx.status = 301
})

// LOGIN
router.post('/login',
  fields('email', 'password'),
  login.login)

// REGISTER
router.post('/register',
  fields('email', 'password', 'name', 'platform', 'nickname'),
  register.create)

// PROFILE
router.get('/profile',
  Authentication.isAuthenticated, Permission.required(['user.read.me']),
  profile.read)

// ANOPE
router.post('/anope',
  Authentication.isWhitelisted,
  AnopeWebhook.update)

// OAUTH2
router.get('/oauth2/authorize',
  Authentication.isAuthenticated,
  oauth2.authorizationValidateRedirect,
  oauth2.authorizationRender
)

router.post('/oauth2/authorize',
  Authentication.isAuthenticated,
  ...oauth2.server.decision())

router.post('/oauth2/token',
  Authentication.isClientAuthenticated,
  oauth2.server.token(),
  oauth2.server.errorHandler())

router.post('/oauth2/revoke',
  Authentication.isClientAuthenticated,
  oauth2.revoke)
router.post('/oauth2/revokeall',
  Authentication.isClientAuthenticated,
  oauth2.revokeAll)

// STATISTICS
router.get('/statistics/rescues',
  statistics.rescues)

router.get('/statistics/systems',
  statistics.systems)

router.get('/statistics/rats',
  statistics.rats)

// VERSION
router.get('/version', version.read)

// RESET
router.post('/reset',
  fields('email'),
  reset.requestReset)

router.get('/reset/:token',
  params('token'),
  reset.validateReset)

router.post('/reset/:token',
  params('token'),
  fields('password'),
  reset.resetPassword)

// DECALS
router.get('/decals/check',
  Authentication.isAuthenticated,
  decal.check)

router.get('/decals/redeem',
  Authentication.isAuthenticated,
  decal.redeem)

// JIRA
router.post('/jira/drill',
  Authentication.isAuthenticated,
  Permission.required(['user.write']),
  jiraDrill.update)

app.use(router.routes())
app.use(router.allowedMethods())

/**
 * Parses an object of URL query parameters and builds a nested object by delimiting periods into sub objects.
 * @param query an array of URL query parameters
 * @returns {{}} a nested object
 */
function parseQuery (query) {
  let queryObj = {}

  // Iterate over each individual query item
  for (let key of Object.keys(query)) {
    // Split them into period delimited arrays
    let keys = key.split('.')
    let target = queryObj

    // Iterate over the period delimited arrays to construct a nested hierarchy
    for (let keyPair of keys.entries()) {
      let [, subkey ] = keyPair
      if (keyPair[0] === keys.length - 1) {
        // We have reached the end of the delimited array which means we can insert the value

        target[subkey] = query[key]
      } else if (!target[subkey]) {
        /* We have not reached the end of the delimited array so we need to create a nested object unless
        it already exists */
        target[subkey] = {}
        target = target[subkey]
      }
    }
  }
  return queryObj
}

let server = http.createServer(app.callback())
const wss = new ws.Server({ server })

const websocketManager = new WebSocketManager(wss, traffic)

wss.on('connection', async function connection (client, req) {
  let url = new URL(`http://localhost:8082${req.url}`)
  client.req = req
  client.clientId = uid.sync(GLOBAL.WEBSOCKET_IDENTIFIER_ROUNDS)
  client.subscriptions = []

  let bearer = url.searchParams.get('bearer')
  if (bearer) {
    let { user, scope } = await Authentication.bearerAuthenticate(bearer)
    if (user) {
      client.user = user
      client.scope = scope
    }
  }

  websocketManager.onConnection(client)

  client.on('message', (message) => {
    client.websocket = wss
    try {
      let request = JSON.parse(message)
      websocketManager.onMessage(client, request)
    } catch (ex) {
      logger.info('Failed to parse incoming websocket message')
    }
  })
})

/**
 * Goes through an object and sets properties commonly usde to hold sensitive information to a static value.
 * @param obj The object to censor
 * @returns {{}} A censored object
 */
function censor (obj) {
  let censoredObj = {}
  Object.assign(censoredObj, obj)

  if (censoredObj.password) {
    censoredObj.password = '[CENSORED]'
  }
  if (censoredObj.secret) {
    censoredObj.secret = '[CENSORED]'
  }

  return censoredObj
}

/**
 * Makes sure the request object has the required data fields specified
 * @param requiredFields The data fields to require
 * @returns {Function} A promise
 */
function fields (...requiredFields) {
  return function (ctx, next) {
    let missingFields = requiredFields.filter((requiredField) => {
      return ctx.data.hasOwnProperty(requiredField) === false
    })
    if (missingFields.length > 0) {
      throw missingFields.map((field) => {
        return new BadRequestAPIError({ pointer: `/data/attributes/${field}` })
      })
    }
    return next()
  }
}

/**
 * Makes sure the request object has the required params specified
 * @param requiredFields The data fields to require
 * @returns {Function} A promise
 */
function params (...requiredFields) {
  return function (ctx, next) {
    let missingFields = requiredFields.filter((requiredField) => {
      return ctx.query.hasOwnProperty(requiredField) === false
    })
    if (missingFields.length > 0) {
      throw missingFields.map((field) => {
        return new BadRequestAPIError({ parameter: field })
      })
    }
    return next()
  }
}

/**
 * Removes the specified data fields from the request object
 * @param cleanFields The data fields to clean away
 * @returns {Function} A promise
 */
function clean (...cleanFields) {
  return function (ctx, next) {
    if (Array.isArray(ctx.data) || typeof ctx.data === 'object') {
      cleanFields.map((cleanField) => {
        ctx.data[cleanField] = undefined
      })
    }
    return next()
  }
}

(async function startServer () {
  try {
    await db.sync()
    const listen = promisify(server.listen.bind(server))
    await listen(port, config.hostname)
    logger.info(`HTTP Server listening on ${config.hostname} port ${port}`)
  } catch (error) {
    logger.error(error)
  }
})()

// allow launch of app from unit tests
module.exports = server<|endoftext|>


<commit_before>'use strict';

const chai = require('chai');
const expect = chai.expect;
const xmlrpc = require('xmlrpc');
const rosnodejs = require('../src/index.js');
const Master = require('./utils/MasterStub.js');

const MASTER_PORT = 11234;

describe('OnTheFly', function () {
  let master;

  before(function() {
    this.timeout(0);

    master = new Master('localhost', MASTER_PORT);
    master.provideAll();

    return rosnodejs.initNode('/testNode', {
      rosMasterUri: `http://localhost:${MASTER_PORT}`,
      onTheFly: true,
      notime: true,
      logging: {skipRosLogging: true}})
  });

  after(() => {
    rosnodejs.reset();
    return master.shutdown();
  });

  const geometry_msgs = rosnodejs.require('geometry_msgs').msg;
  const msg = new geometry_msgs.PoseWithCovariance({
      pose: {
        position: {x:0, y:0, z:0},
        orientation: {w:1, x:0, y:0, z:0}
      },
      covariance: [
        0,0,0,0,0,0.123,
        0,2,0,0,0,0,
        0,0,4,0,0,0,
        0,0,0,6,0,0,
        0,0,0,0,8,0,
        0.123,0,0,0,0,0.654321654321
      ]
    });

  it('serialize/deserialize', (done) => {
    const size = geometry_msgs.PoseWithCovariance.getMessageSize(msg);
    const buffer = new Buffer(size);
    geometry_msgs.PoseWithCovariance.serialize(msg, buffer, 0);

    const read = geometry_msgs.PoseWithCovariance.deserialize(buffer);
    expect(read.covariance.length == msg.covariance.length
      && read.covariance.every((v,i)=> v === msg.covariance[i])).to.be.true;

    done();
  });
});
<commit_msg>Add test for UTF-8 string content (#133)<commit_after>'use strict';

const chai = require('chai');
const expect = chai.expect;
const xmlrpc = require('xmlrpc');
const rosnodejs = require('../src/index.js');
const Master = require('./utils/MasterStub.js');

const MASTER_PORT = 11234;

describe('OnTheFly', function () {
  let master;

  before(function() {
    this.timeout(0);

    master = new Master('localhost', MASTER_PORT);
    master.provideAll();

    return rosnodejs.initNode('/testNode', {
      rosMasterUri: `http://localhost:${MASTER_PORT}`,
      onTheFly: true,
      notime: true,
      logging: {skipRosLogging: true}})
  });

  after(() => {
    rosnodejs.reset();
    return master.shutdown();
  });

  it('serialize/deserialize PoseWithCovariance', (done) => {
    const geometry_msgs = rosnodejs.require('geometry_msgs').msg;
    const msg = new geometry_msgs.PoseWithCovariance({
        pose: {
          position: {x:0, y:0, z:0},
          orientation: {w:1, x:0, y:0, z:0}
        },
        covariance: [
          0,0,0,0,0,0.123,
          0,2,0,0,0,0,
          0,0,4,0,0,0,
          0,0,0,6,0,0,
          0,0,0,0,8,0,
          0.123,0,0,0,0,0.654321654321
        ]
      });

    const size = geometry_msgs.PoseWithCovariance.getMessageSize(msg);
    const buffer = new Buffer(size);
    geometry_msgs.PoseWithCovariance.serialize(msg, buffer, 0);

    const read = geometry_msgs.PoseWithCovariance.deserialize(buffer);
    expect(read.covariance.length == msg.covariance.length
      && read.covariance.every((v,i)=> v === msg.covariance[i])).to.be.true;

    done();
  });

  it('serialize/deserialize String', (done) => {
    const std_msgs = rosnodejs.require('std_msgs').msg;
    const data = 'sДvΣ τhΣ 子猫';  // Test with multi-byte UTF-8 characters.
                                   // If this test fails, you killed a kitten.
    const msg = new std_msgs.String({ data: data });

    const size = std_msgs.String.getMessageSize(msg);

    const buffer = new Buffer(size);
    std_msgs.String.serialize(msg, buffer, 0);

    const read = std_msgs.String.deserialize(buffer);
    expect(read.data).to.deep.equal(data);

    done();
  });
});
<|endoftext|>


<commit_before>var render = require("./render")

var domIndex = require("./lib/dom-index")
var isArray = require("./lib/is-array")
var isString = require("./lib/is-string")

module.exports = patch

function patch(rootNode, patches) {
    var index = domIndex(rootNode, patches.a, patches)

    for (var nodeIndex in patches) {
        if (nodeIndex === "a") {
            continue
        }

        rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex])
    }

    return rootNode
}

function applyPatch(rootNode, domNode, patchList) {
    if (!domNode || !isArray(patchList)) {
        return rootNode
    }

    for (var i = 0; i < patchList.length; i++) {
        var op = patchList[i]

        if (op.type === "remove") {
            remove(domNode)
            if (op.widget) {
                op.widget.destroy()
            }
        } else if (op.type ===  "insert") {
            if (op.widget) {
                insert(domNode, op.widget.init())
            } else {
                insert(domNode, render(op.b))
            }
        } else if (op.type === "replace") {
            if (domNode === rootNode) {
                rootNode = render(op.b)
            } else {
                replace(domNode, render(op.b))
            }
        } else if (op.type === "update") {
            update(domNode, op.patch)
        }
    }

    return rootNode
}

function remove(domNode) {
    var parent = domNode.parentNode
    if (parent) {
        parent.removeChild(domNode)
    }
}

function insert(domNode, child) {
    if (domNode.nodeType === 1) {
        domNode.appendChild(child)
    }
}

function replace(domNode, newNode) {
    var parent = domNode.parentNode
    if (parent) {
        parent.replaceChild(newNode, domNode)
    }
}

function update(domNode, patch) {
    if (isString(patch)) {
        if (domNode.nodeType === 3) {
            domNode.replaceData(patch)
        } else  if (patch.a && patch.bl) {
            // update widget
            var wNode = patch.a.update(patch.b)
            if (domNode !== wNode) {
                replace(domNode, wNode)
            }
        } else {
            replace(domNode, render(patch))
        }
    } else {
        for (var prop in patch) {
            if (prop === "style") {
                var stylePatch = patch.style
                var domStyle = domNode.style
                for (var s in stylePatch) {
                    domStyle[s] = stylePatch[s]
                }
            } else {
                var patchValue = patch[prop]

                if (typeof patchValue === "function") {
                    patchValue(domNode, prop)
                } else {
                    domNode[prop] = patchValue
                }
            }
        }
    }
}
<commit_msg>fix replaceData signature<commit_after>var render = require("./render")

var domIndex = require("./lib/dom-index")
var isArray = require("./lib/is-array")
var isString = require("./lib/is-string")

module.exports = patch

function patch(rootNode, patches) {
    var index = domIndex(rootNode, patches.a, patches)

    for (var nodeIndex in patches) {
        if (nodeIndex === "a") {
            continue
        }

        rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex])
    }

    return rootNode
}

function applyPatch(rootNode, domNode, patchList) {
    if (!domNode || !isArray(patchList)) {
        return rootNode
    }

    for (var i = 0; i < patchList.length; i++) {
        var op = patchList[i]

        if (op.type === "remove") {
            remove(domNode)
            if (op.widget) {
                op.widget.destroy()
            }
        } else if (op.type ===  "insert") {
            if (op.widget) {
                insert(domNode, op.widget.init())
            } else {
                insert(domNode, render(op.b))
            }
        } else if (op.type === "replace") {
            if (domNode === rootNode) {
                rootNode = render(op.b)
            } else {
                replace(domNode, render(op.b))
            }
        } else if (op.type === "update") {
            update(domNode, op.patch)
        }
    }

    return rootNode
}

function remove(domNode) {
    var parent = domNode.parentNode
    if (parent) {
        parent.removeChild(domNode)
    }
}

function insert(domNode, child) {
    if (domNode.nodeType === 1) {
        domNode.appendChild(child)
    }
}

function replace(domNode, newNode) {
    var parent = domNode.parentNode
    if (parent) {
        parent.replaceChild(newNode, domNode)
    }
}

function update(domNode, patch) {
    if (isString(patch)) {
        if (domNode.nodeType === 3) {
            domNode.replaceData(0, patch.length, patch)
        } else  if (patch.a && patch.bl) {
            // update widget
            var wNode = patch.a.update(patch.b)
            if (domNode !== wNode) {
                replace(domNode, wNode)
            }
        } else {
            replace(domNode, render(patch))
        }
    } else {
        for (var prop in patch) {
            if (prop === "style") {
                var stylePatch = patch.style
                var domStyle = domNode.style
                for (var s in stylePatch) {
                    domStyle[s] = stylePatch[s]
                }
            } else {
                var patchValue = patch[prop]

                if (typeof patchValue === "function") {
                    patchValue(domNode, prop)
                } else {
                    domNode[prop] = patchValue
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>import Rx from 'rx'

let isNode = typeof process !== 'undefined' && process.versions && !!process.versions.node
if(isNode){
  const XMLHttpRequest = require("xhr2").XMLHttpRequest
}

export function createResponse$(options){
  const defaults = {
    method:'get'
    ,encoding:'utf8'
    ,mimeType:'text/plain; charset=x-user-defined'
    ,responseType:''
    ,timeout:undefined
    ,send:undefined
  }
  options = Object.assign({}, defaults, options)

  let obs = new Rx.Subject()

  let request = new XMLHttpRequest()

  function handleProgress(e){
    [e]
      .filter(e=>e.lengthComputable)
      .forEach(function(e){
          obs.onNext({progress: (e.loaded / e.total),total:e.total})
      })
  }
  function handleComplete(e){
    let response = request.response
    if(request.responseType === ''  || (request.responseType === 'text' && response === null || response === undefined)){
      response = request.responseText
    }

    const status = parseInt((request.status + '').charAt(0))
    const statusWhiteList = [1,2]//valid http status codes are 1XX or 2XX , nothing else
    if(statusWhiteList.indexOf(status)===-1){
      obs.onError(e)
    }else{
      //response = options.responseType === 'json' ? JSON.parse(response) : response
      obs.onNext({response})
      obs.onCompleted()
    }

  }

  function handleError(e){
    console.log("error in httpDriver",e)
    obs.onError(e)
  }

  function handleAbort(e){
    console.log("abort in httpDriver",e)
    obs.onError(e)
  }

  function handleTimeout(e){
    console.log("timeout in httpDriver",e)
    obs.onError(e)
  }

  request.addEventListener("progress", handleProgress)
  request.addEventListener("load"    , handleComplete)
  request.addEventListener("error"   , handleError)
  request.addEventListener("abort"   , handleError)
  request.addEventListener("timeout" , handleTimeout)

  request.open(options.method,options.url, true)
  if ((options.mimeType !== null) && (request.overrideMimeType !== null)) {
    request.overrideMimeType(options.mimeType)
  }
  request.timeout      = options.timeout
  request.responseType = options.responseType

  request.send(options.send)

  return obs
}

export default function makeHttpDriver({eager = false} = {eager: false}){

  return function httpDriver(request$){
    let response$$ = request$
      .map(reqOptions => {
        let response$ = createResponse$(reqOptions)
        if (eager || reqOptions.eager) {
            response$ = response$.replay(null, 1)
            response$.connect()
        }
        response$.request = reqOptions
        return response$
      })
      .replay(null, 1)
    response$$.connect()
    return response$$
  }
}
<commit_msg>feat(added support for withCredentials)<commit_after>import Rx from 'rx'

let isNode = typeof process !== 'undefined' && process.versions && !!process.versions.node
if (isNode) {
  const XMLHttpRequest = require('xhr2').XMLHttpRequest
}

export function createResponse$ (options) {
  const defaults = {
    method: 'get',
    encoding: 'utf8',
    mimeType: 'text/plain; charset=x-user-defined',
    responseType: '',
    timeout: undefined,
    send: undefined,
    withCredentials: true
  }
  options = Object.assign({}, defaults, options)

  let obs = new Rx.Subject()

  let request = new XMLHttpRequest()

  function handleProgress (e) {
    [e]
      .filter(e => e.lengthComputable)
      .forEach(function (e) {
        obs.onNext({progress: (e.loaded / e.total), total: e.total})
      })
  }
  function handleComplete (e) {
    let response = request.response
    if (request.responseType === '' || (request.responseType === 'text' && response === null || response === undefined)) {
      response = request.responseText
    }

    const status = parseInt((request.status + '').charAt(0), 10)
    const statusWhiteList = [1, 2] // valid http status codes are 1XX or 2XX , nothing else
    if (statusWhiteList.indexOf(status) === -1) {
      obs.onError(e)
    } else {
      // response = options.responseType === 'json' ? JSON.parse(response) : response
      obs.onNext({response})
      obs.onCompleted()
    }
  }

  function handleError (e) {
    console.log('error in httpDriver', e)
    obs.onError(e)
  }

  function handleAbort (e) {
    console.log('abort in httpDriver', e)
    obs.onError(e)
  }

  function handleTimeout (e) {
    console.log('timeout in httpDriver', e)
    obs.onError(e)
  }

  request.addEventListener('progress', handleProgress)
  request.addEventListener('load', handleComplete)
  request.addEventListener('error', handleError)
  request.addEventListener('abort', handleError)
  request.addEventListener('timeout', handleTimeout)

  request.open(options.method, options.url, true)
  if ((options.mimeType !== null) && (request.overrideMimeType !== null)) {
    request.overrideMimeType(options.mimeType)
  }
  request.timeout = options.timeout
  request.responseType = options.responseType
  request.withCredentials = options.withCredentials

  request.send(options.send)

  return obs
}

export default function makeHttpDriver ({ eager = false } = {eager: false}) {
  return function httpDriver (request$) {
    let response$$ = request$
      .map(reqOptions => {
        let response$ = createResponse$(reqOptions)
        if (eager || reqOptions.eager) {
          response$ = response$.replay(null, 1)
          response$.connect()
        }
        response$.request = reqOptions
        return response$
      })
      .replay(null, 1)
    response$$.connect()
    return response$$
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var Ontology = require('../ontology'),
    assert = require('assert')

describe('Ontology', function() {

    var json = [
        ["arachnid", "animal"],
        ["mammal", "animal"],
        ["spider", "arachnid"],
        ["primate", "mammal"],
        ["man", "primate"],
        ["spiderman", "spider", "man"],
        ["kingkong", "primate"]
    ]

    var onto = new Ontology (json)
    var ontoJson = onto.toJSON()

    var jsonFull = json.slice()
    jsonFull.push (["animal"])

    var ontoFull = new Ontology (jsonFull)
    var ontoJsonFull = ontoFull.toJSON()

    describe('#constructor', function() {
        it('should detect implicit terms', function() {
            assert (onto.terms() == 8)
            assert (onto.termName[7] == 'animal')
        })
    })

    describe('#toJSON', function() {
        it('should be idempotent when composed with constructor', function() {
            assert (JSON.stringify(jsonFull) == JSON.stringify(ontoJsonFull))
        })
    })

    describe('#terms', function() {
        it('should yield the number of terms', function() {
            assert (ontoFull.terms() == jsonFull.length)
        })
    })
})
<commit_msg>added comment to ontology test<commit_after>// for use with mocha test framework

var Ontology = require('../ontology'),
    assert = require('assert')

describe('Ontology', function() {

    var json = [
        ["arachnid", "animal"],
        ["mammal", "animal"],
        ["spider", "arachnid"],
        ["primate", "mammal"],
        ["man", "primate"],
        ["spiderman", "spider", "man"],
        ["kingkong", "primate"]
    ]

    var onto = new Ontology (json)
    var ontoJson = onto.toJSON()

    var jsonFull = json.slice()
    jsonFull.push (["animal"])

    var ontoFull = new Ontology (jsonFull)
    var ontoJsonFull = ontoFull.toJSON()

    describe('#constructor', function() {
        it('should detect implicit terms', function() {
            assert (onto.terms() == 8)
            assert (onto.termName[7] == 'animal')
        })
    })

    describe('#toJSON', function() {
        it('should be idempotent when composed with constructor', function() {
            assert (JSON.stringify(jsonFull) == JSON.stringify(ontoJsonFull))
        })
    })

    describe('#terms', function() {
        it('should yield the number of terms', function() {
            assert (ontoFull.terms() == jsonFull.length)
        })
    })
})
<|endoftext|>


<commit_before>var petri = (function() {
	var module = {};

	var dotDensity = 2.5;

	function resizeCanvas(canvas) {
		canvas.height = canvas.height;
		canvas.width = canvas.width;
	}

	function setBackground(elem) {
		var colors = ["336699","20C29A","8C20C2","0E193D"];
		//var colors = ["0E193D", "011123"]
		if(colors.length > 1) {
			var n = random(0,colors.length-1);
			var m = (n + random(1,colors.length-2)) % colors.length;
			setBackgroundGradient(elem, colors[n], colors[m], random(60,120));
		}
		colors = null;
	}

	/**
	* Establece un degradado como color de fondo de un elemento DOM
	* @param elemento objeto al que se aplica el color de fondo
	* @param hex1 Color 1 en hexadecimal (sin #)
	* @param hex2 Color 2 en hexadecimal (sin #)
	* @param degrees Inclinación del degradado
	*/
	function setBackgroundGradient(elem, hex1, hex2, degrees) {
		elem.style.backgroundImage = "linear-gradient(" + degrees + "deg, #" + hex1 + ", #" + hex2 + ")";
	}

	/**
	* Returns a random number between A and B, both included.
	* @param {number} min - Minimum value.
	* @param {number} max - Maximum value.
	*/
	function random(min, max) {
		return Math.floor(Math.random() * (max - min + 1) + min);
	}

	/**
	* Round module including negative numbers.
	* Example: -1 % 4 === 3
	* @param {number} div - Dividend
	* @param {number} dsor - Divisor
	*/
	function round_mod(div, dsor) {
		return ((div % dsor) + dsor) % dsor;
	}

	const TWO_PI = 2 * Math.PI;

	const DOT_MIN_RADIUS = 1;
	const DOT_MAX_RADIUS = 2;
	const DOT_MIN_SPEED = 4;
	const DOT_MAX_SPEED = 12;

	const MAX_DISTANCE_UNION = 100;

	const DRAW_DOT_COLOR = 'rgba(255,255,255,0.75)';

	function Dot(canvas, x, y, radius) {
		this._init(canvas, x, y, radius);
	}

	Dot.prototype = {
		_init: function(canvas, x, y, radius) {
			this.canvas = canvas;
			this.context = canvas.getContext('2d');

			this.x = x;
			this.y = y;
			this.radius = radius;
			this.vx = 0;
			this.vy = 0;

			this.adjacents = [];
			this.painted = false;
		},

		distance: function(other) {
			var dx = this.x - other.x,
			    dy = this.y - other.y;
			return Math.sqrt(dx * dx + dy * dy);
		},

		step: function(dt) {
			this.x = round_mod(this.x + this.vx * dt, canvas.width);
			this.y = round_mod(this.y + this.vy * dt, canvas.height);
			this.painted = false;
		},

		draw: function() {
			let canvas = this.context;
			canvas.beginPath();
			canvas.fillStyle = DRAW_DOT_COLOR;
			canvas.arc(this.x, this.y, this.radius, 0, TWO_PI);
			canvas.fill();

			// canvas.beginPath();
			// canvas.strokeStyle = 'rgba(255,0,0,1)';
			// canvas.lineWidth = 0.5;
			// canvas.arc(this.x, this.y, MAX_DISTANCE_UNION, 0, TWO_PI);
			// canvas.stroke();

			this._draw_unions();
			this.painted = true;
		},

		_draw_unions: function() {
			var neighbor;
			for(let i = 0; i < this.adjacents.length; ++i) {
				neighbor = this.adjacents[i];
				if(!neighbor.painted) {
					this._draw_union_with(neighbor);
				}
			}
		},

		_draw_union_with: function(other) {
			let canvas = this.context;
			let opacity = (1 - this.distance(other) / MAX_DISTANCE_UNION); // Max opacity is 0.75, min is 0
			opacity *= opacity * 0.9;

			canvas.beginPath();
			canvas.strokeStyle = 'rgba(255,255,255,' + opacity + ')';
			canvas.lineWidth = 1;
			canvas.moveTo(this.x, this.y);
			canvas.lineTo(other.x, other.y);
			canvas.stroke();
		}
	}

	function RandomDot(canvas) {
		this._init(canvas);
	}

	RandomDot.prototype = {
		__proto__: Dot.prototype,

		_init: function(canvas) {
			let pos_x = Math.random() * canvas.width;
			let pos_y = Math.random() * canvas.height;
			let radius = random(DOT_MIN_RADIUS, DOT_MAX_RADIUS);
			Dot.prototype._init.call(this, canvas, pos_x, pos_y, radius);

			this._init_movement();
		},

		_init_movement: function() {
			// The smaller the slower (because it's supposed to be farther)
			var speed = DOT_MIN_SPEED + (DOT_MAX_SPEED - DOT_MIN_SPEED) *
			            (this.radius - DOT_MIN_RADIUS) / (DOT_MAX_RADIUS - DOT_MIN_RADIUS);
			var direction = Math.random() * TWO_PI;
			this.vx = speed * Math.cos(direction);
			this.vy = speed * Math.sin(direction);
		},
	}

	function Grid(width, height) {
		this._init.apply(this, arguments);
	}

	Grid.prototype = {
		_init: function(width, height) {
			if(width <= 0 || height <= 0)
				throw "Size units must be positive: (" + width + "," + height + ")";

			this.width = width;
			this.height = height;

			this.columns = this.rows = 6;

			this.grid = new Array(this.rows);
			for(let i = 0; i < this.rows; ++i) {
				this.grid[i] = new Array(this.columns);
				for(let j = 0; j < this.columns; ++j) {
					this.grid[i][j] = [];
				}
			}
		},

		insert: function(point) {
			var section = this.get_section(point.x, point.y);
			if(section.indexOf(point) < 0) {
				section.push(point);
			}
		},

		update_point: function(old_x, old_y, point) {
			let old_section = this.get_section(old_x, old_y);
			let pos = old_section.indexOf(point);

			if(pos < 0)
				return;

			old_section.splice(pos, 1);

			let new_section = this.get_section(point.x, point.y);
			new_section.push(point);
		},

		get_section: function(x, y) {
			return this.grid[this.get_row(y)][this.get_column(x)];
		},

		get_column: function(x) {
			return Math.floor(x * this.columns / this.width);
		},

		get_row: function(y) {
			return Math.floor(y * this.rows / this.height);
		},

		visible_points: function(point, radius) {
			var visible = [];
			var init_col = Math.max(this.get_column(point.x - radius), 0),
			     end_col = Math.min(this.get_column(point.x + radius) + 1, this.columns);
			var init_row = Math.max(this.get_row(point.y - radius), 0),
			     end_row = Math.min(this.get_row(point.y + radius) + 1, this.rows);

			for(let i = init_row; i < end_row; ++i) {
				for(let j = init_col; j < end_col; ++j) {
					this.grid[i][j].forEach(function(other) {
						if(point.distance(other) <= radius) {
							visible.push(other);
						}
					});
				}
			}
			return visible;
		}
	}

	function Petri(canvas, n_points) {
		this._init(canvas, n_points);
	}

	Petri.prototype = {
		_init: function(canvas, n_points) {
			this.canvas = canvas;
			this.context = canvas.getContext('2d');
			this.width = canvas.width;
			this.height = canvas.height;

			this.surface = new Grid(this.width, this.height);

			this.points = new Array(n_points);
			for(let i = 0; i < n_points; ++i) {
				this.points[i] = new RandomDot(this.canvas);
				this.surface.insert(this.points[i]);
			}
		},

		_update_graph: function () {
			var point;
			for(let i = 0; i < this.points.length; ++i) {
				point = this.points[i];
				point.adjacents = this.surface.visible_points(point, MAX_DISTANCE_UNION);
			}
		},

		start: function() {
			if(this.run) return;

			this.run = true;
			this.time = performance.now();
			window.requestAnimationFrame(this._step_frame.bind(this));
		},

		stop: function () {
			this.run = false;
		},

		_step_frame: function(current_time) {
			let time_diff = (current_time - this.time) / 1000;
			this.step(time_diff);
			this.draw();

			this.time = current_time;

			if(this.run) {
				window.requestAnimationFrame(this._step_frame.bind(this));
			}
		},

		step: function(dt) {
			var point;
			var old_x, old_y;
			for(let i = 0; i < this.points.length; ++i) {
				point = this.points[i];
				old_x = point.x; old_y = point.y;
				point.step(dt);
				this.surface.update_point(old_x, old_y, point);
			}
			this._update_graph();
		},

		draw: function() {
			var point;

			this.context.clearRect(0 , 0, this.canvas.width, this.canvas.height);
			for(let i = 0; i < this.points.length; ++i) {
				point = this.points[i];
				point.draw();
			}
		}
	}

	module.Petri = Petri;

	return module;
})();
<commit_msg>Add cursor dot<commit_after>var petri = (function() {
	var module = {};

	var dotDensity = 2.5;

	function resizeCanvas(canvas) {
		canvas.height = canvas.height;
		canvas.width = canvas.width;
	}

	function setBackground(elem) {
		var colors = ["336699","20C29A","8C20C2","0E193D"];
		//var colors = ["0E193D", "011123"]
		if(colors.length > 1) {
			var n = random(0,colors.length-1);
			var m = (n + random(1,colors.length-2)) % colors.length;
			setBackgroundGradient(elem, colors[n], colors[m], random(60,120));
		}
		colors = null;
	}

	/**
	* Establece un degradado como color de fondo de un elemento DOM
	* @param elemento objeto al que se aplica el color de fondo
	* @param hex1 Color 1 en hexadecimal (sin #)
	* @param hex2 Color 2 en hexadecimal (sin #)
	* @param degrees Inclinación del degradado
	*/
	function setBackgroundGradient(elem, hex1, hex2, degrees) {
		elem.style.backgroundImage = "linear-gradient(" + degrees + "deg, #" + hex1 + ", #" + hex2 + ")";
	}

	/**
	* Returns a random number between A and B, both included.
	* @param {number} min - Minimum value.
	* @param {number} max - Maximum value.
	*/
	function random(min, max) {
		return Math.floor(Math.random() * (max - min + 1) + min);
	}

	/**
	* Round module including negative numbers.
	* Example: -1 % 4 === 3
	* @param {number} div - Dividend
	* @param {number} dsor - Divisor
	*/
	function round_mod(div, dsor) {
		return ((div % dsor) + dsor) % dsor;
	}

	const TWO_PI = 2 * Math.PI;

	const DOT_MIN_RADIUS = 1;
	const DOT_MAX_RADIUS = 2;
	const DOT_MIN_SPEED = 4;
	const DOT_MAX_SPEED = 12;

	const MAX_DISTANCE_UNION = 100;

	const DRAW_DOT_COLOR = 'rgba(255,255,255,0.75)';

	function Dot(canvas, x, y, radius) {
		this._init(canvas, x, y, radius);
	}

	Dot.prototype = {
		_init: function(canvas, x, y, radius) {
			this.canvas = canvas;
			this.context = canvas.getContext('2d');

			this.x = x;
			this.y = y;
			this.radius = radius;
			this.vx = 0;
			this.vy = 0;

			this.adjacents = [];
			this.painted = false;
		},

		distance: function(other) {
			var dx = this.x - other.x,
			    dy = this.y - other.y;
			return Math.sqrt(dx * dx + dy * dy);
		},

		step: function(dt) {
			this.x = round_mod(this.x + this.vx * dt, canvas.width);
			this.y = round_mod(this.y + this.vy * dt, canvas.height);
			this.painted = false;
		},

		draw: function() {
			let canvas = this.context;
			canvas.beginPath();
			canvas.fillStyle = DRAW_DOT_COLOR;
			canvas.arc(this.x, this.y, this.radius, 0, TWO_PI);
			canvas.fill();

			// canvas.beginPath();
			// canvas.strokeStyle = 'rgba(255,0,0,1)';
			// canvas.lineWidth = 0.5;
			// canvas.arc(this.x, this.y, MAX_DISTANCE_UNION, 0, TWO_PI);
			// canvas.stroke();

			this._draw_unions();
			this.painted = true;
		},

		_draw_unions: function() {
			var neighbor;
			for(let i = 0; i < this.adjacents.length; ++i) {
				neighbor = this.adjacents[i];
				if(!neighbor.painted) {
					this._draw_union_with(neighbor);
				}
			}
		},

		_draw_union_with: function(other) {
			let canvas = this.context;
			let opacity = (1 - this.distance(other) / MAX_DISTANCE_UNION); // Max opacity is 0.75, min is 0
			opacity *= opacity * 0.9;

			canvas.beginPath();
			canvas.strokeStyle = 'rgba(255,255,255,' + opacity + ')';
			canvas.lineWidth = 1;
			canvas.moveTo(this.x, this.y);
			canvas.lineTo(other.x, other.y);
			canvas.stroke();
		}
	}

	function RandomDot(canvas) {
		this._init(canvas);
	}

	RandomDot.prototype = {
		__proto__: Dot.prototype,

		_init: function(canvas) {
			let pos_x = Math.random() * canvas.width;
			let pos_y = Math.random() * canvas.height;
			let radius = random(DOT_MIN_RADIUS, DOT_MAX_RADIUS);
			Dot.prototype._init.call(this, canvas, pos_x, pos_y, radius);

			this._init_movement();
		},

		_init_movement: function() {
			// The smaller the slower (because it's supposed to be farther)
			var speed = DOT_MIN_SPEED + (DOT_MAX_SPEED - DOT_MIN_SPEED) *
			            (this.radius - DOT_MIN_RADIUS) / (DOT_MAX_RADIUS - DOT_MIN_RADIUS);
			var direction = Math.random() * TWO_PI;
			this.vx = speed * Math.cos(direction);
			this.vy = speed * Math.sin(direction);
		},
	}

	function CursorDot(canvas) {
		this._init(canvas);
	}

	CursorDot.prototype = {
		__proto__: Dot.prototype,

		_init: function(canvas) {
			Dot.prototype._init.call(this, canvas, 0, 0, 0);

			window.addEventListener('mousemove', this);
		},

		handleEvent: function(event) {
			this.x = event.clientX;
			this.y = event.clientY;
		},

		draw: function () {
			for(let i = 0; i < this.adjacents.length; ++i) {
				this._draw_union_with(this.adjacents[i]);
			}
		}
	}

	function Grid(width, height) {
		this._init.apply(this, arguments);
	}

	Grid.prototype = {
		_init: function(width, height) {
			if(width <= 0 || height <= 0)
				throw "Size units must be positive: (" + width + "," + height + ")";

			this.width = width;
			this.height = height;

			this.columns = this.rows = 6;

			this.grid = new Array(this.rows);
			for(let i = 0; i < this.rows; ++i) {
				this.grid[i] = new Array(this.columns);
				for(let j = 0; j < this.columns; ++j) {
					this.grid[i][j] = [];
				}
			}
		},

		insert: function(point) {
			var section = this.get_section(point.x, point.y);
			if(section.indexOf(point) < 0) {
				section.push(point);
			}
		},

		update_point: function(old_x, old_y, point) {
			let old_section = this.get_section(old_x, old_y);
			let pos = old_section.indexOf(point);

			if(pos < 0)
				return;

			old_section.splice(pos, 1);

			let new_section = this.get_section(point.x, point.y);
			new_section.push(point);
		},

		get_section: function(x, y) {
			return this.grid[this.get_row(y)][this.get_column(x)];
		},

		get_column: function(x) {
			return Math.floor(x * this.columns / this.width);
		},

		get_row: function(y) {
			return Math.floor(y * this.rows / this.height);
		},

		visible_points: function(point, radius) {
			var visible = [];
			var init_col = Math.max(this.get_column(point.x - radius), 0),
			     end_col = Math.min(this.get_column(point.x + radius) + 1, this.columns);
			var init_row = Math.max(this.get_row(point.y - radius), 0),
			     end_row = Math.min(this.get_row(point.y + radius) + 1, this.rows);

			for(let i = init_row; i < end_row; ++i) {
				for(let j = init_col; j < end_col; ++j) {
					this.grid[i][j].forEach(function(other) {
						if(point.distance(other) <= radius) {
							visible.push(other);
						}
					});
				}
			}
			return visible;
		}
	}

	function Petri(canvas, n_points) {
		this._init(canvas, n_points);
	}

	Petri.prototype = {
		_init: function(canvas, n_points) {
			this.canvas = canvas;
			this.context = canvas.getContext('2d');
			this.width = canvas.width;
			this.height = canvas.height;

			this.surface = new Grid(this.width, this.height);

			this.points = new Array(n_points);
			for(let i = 0; i < n_points; ++i) {
				this.points[i] = new RandomDot(this.canvas);
				this.surface.insert(this.points[i]);
			}
			this.cursor = new CursorDot(this.canvas);
		},

		_update_graph: function () {
			var point;
			for(let i = 0; i < this.points.length; ++i) {
				point = this.points[i];
				point.adjacents = this.surface.visible_points(point, MAX_DISTANCE_UNION);
			}
			this.cursor.adjacents = this.surface.visible_points(this.cursor, MAX_DISTANCE_UNION);
		},

		start: function() {
			if(this.run) return;

			this.run = true;
			this.time = performance.now();
			window.requestAnimationFrame(this._step_frame.bind(this));
		},

		stop: function () {
			this.run = false;
		},

		_step_frame: function(current_time) {
			let time_diff = (current_time - this.time) / 1000;
			this.step(time_diff);
			this.draw();

			this.time = current_time;

			if(this.run) {
				window.requestAnimationFrame(this._step_frame.bind(this));
			}
		},

		step: function(dt) {
			var point;
			var old_x, old_y;
			for(let i = 0; i < this.points.length; ++i) {
				point = this.points[i];
				old_x = point.x; old_y = point.y;
				point.step(dt);
				this.surface.update_point(old_x, old_y, point);
			}
			this._update_graph();
		},

		draw: function() {
			var point;

			this.context.clearRect(0 , 0, this.canvas.width, this.canvas.height);
			for(let i = 0; i < this.points.length; ++i) {
				point = this.points[i];
				point.draw();
			}
			this.cursor.draw();
		}
	}

	module.Petri = Petri;

	return module;
})();
<|endoftext|>


<commit_before>import compose from 'koa-compose';
import includes from 'lodash/collection/includes';
import intersection from 'lodash/array/intersection';
import keysIn from 'lodash/object/keysIn';
import route from 'koa-route';

const URL_WITH_NAME = name => `/${name}`;
const URL_WITH_PARAM = name => `/${name}/${name}Param`;
const URL_WITH_NEW = name => `/${name}/new`;
const URL_WITH_EDIT = name => `/${name}/edit`;

// Constant containing our actions
const ACTIONS = {
  'index': {
    method: 'get',
    url: URL_WITH_NAME,
    similar: ['create'],
  },
  'show': {
    method: 'get',
    url: URL_WITH_PARAM,
    similar: ['update', 'destroy'],
  },
  'create': {
    method: 'post',
    url: URL_WITH_NAME,
    similar: ['index'],
  },
  'new': {
    method: 'get',
    url: URL_WITH_NEW,
    similar: [],
  },
  'edit': {
    method: 'get',
    url: URL_WITH_EDIT,
    similar: [],
  },
  'update': {
    method: 'put',
    url: URL_WITH_PARAM,
    similar: ['show', 'destroy'],
  },
  'destroy': {
    method: 'delete',
    url: URL_WITH_PARAM,
    similar: ['show', 'update'],
  },
};

/**
 * A simple middleware that responds to disallowed methods with a 405 response.
 *
 * @param {Array.<String>} actionList List of implemented actions
 * @param {Array.<String>} similarActions List of relevant actions
 *
 * @return {GeneratorFunction}
 */
function methodNotAllowed(actionList, similarActions) {
  let relevantMethods = similarActions.map(action => ACTIONS[action].method.toUpperCase());
  let methods = intersection(actionList, relevantMethods);
  return function* middleware(next) {
    this.status = 400;
    this.set('Allow', methods.join(','));
    yield* next;
  };
}

/**
 * A recursive generator function that yields koa-route middlewares for each route.
 *
 * @param {Object} resources Contains all resources and their actions.
 * @param {String} prefix String to prepend to URL when generating routes.
 * @param {String} resourceName Name of the current resource we are processing.
 *
 * @return {Iterable}
 */
function* getMiddlewares(resources, prefix = '', resourceName = '') {

  // If our resources object is null, return
  if (resources === null || typeof resources !== 'object') return;

  // Determine if this object has actions as properties
  const actionList = intersection(keysIn(resources), keysIn(ACTIONS));
  const hasActions = actionList.length > 0;

  // Iterate through each action if we have at least one action
  if (hasActions) {
    // Check for invariant violations
    if (resourceName === '')
      throw Error(`The root resource object cannot contain actions.`);

    for (const name in ACTIONS) {
      const action = ACTIONS[name];
      yield route[action.method](
        `${prefix}${action.url(resourceName)}`,
        resources[name] || methodNotAllowed(actionList, action.similar)
      );
    }
  }

  // Iterate through the rest of the methods (non-actions)
  for (const key in resources) {
    if (!includes(keysIn(ACTIONS), key)) {
      // Check for invariant violations
      if (typeof resources[key] !== 'function')
        throw Error(`Action '${key}' must be a function.`);

      let innerPrefix;

      // Determine prefix to send to inner resource
      if (resourceName === '') {
        innerPrefix = prefix;
      } else if (hasActions) {
        innerPrefix = `${prefix}/${resourceName}/:${resourceName}Param`;
      } else {
        innerPrefix = `${prefix}/${resourceName}`;
      }

      // Iterate through inner resources
      yield* getMiddlewares(resources[key], innerPrefix, key);
    }
  }
}

/**
 * Creates the middleware given resources and their actions.
 *
 * @param {Object} resources Contains all resources and their actions.
 *
 * @return {GeneratorFunction} The middleware.
 */
export default function resourceRoutes(resources) {
  // Use koa-compose on all REST middlewares generated by getMiddlewares
  return compose(Array.from(getMiddlewares(resources)));
}
<commit_msg>Fixed up a few bugs<commit_after>import compose from 'koa-compose';
import includes from 'lodash/collection/includes';
import intersection from 'lodash/array/intersection';
import keysIn from 'lodash/object/keysIn';
import route from 'koa-route';

const URL_WITH_NAME = name => `/${name}`;
const URL_WITH_PARAM = name => `/${name}/${name}Param`;
const URL_WITH_NEW = name => `/${name}/new`;
const URL_WITH_EDIT = name => `/${name}/edit`;

// Constant containing our actions
const ACTIONS = {
  'index': {
    method: 'get',
    url: URL_WITH_NAME,
    similar: ['create'],
  },
  'show': {
    method: 'get',
    url: URL_WITH_PARAM,
    similar: ['update', 'destroy'],
  },
  'create': {
    method: 'post',
    url: URL_WITH_NAME,
    similar: ['index'],
  },
  'new': {
    method: 'get',
    url: URL_WITH_NEW,
    similar: [],
  },
  'edit': {
    method: 'get',
    url: URL_WITH_EDIT,
    similar: [],
  },
  'update': {
    method: 'put',
    url: URL_WITH_PARAM,
    similar: ['show', 'destroy'],
  },
  'destroy': {
    method: 'delete',
    url: URL_WITH_PARAM,
    similar: ['show', 'update'],
  },
};

/**
 * A simple middleware that responds to disallowed methods with a 405 response.
 *
 * @param {Array.<String>} actionList List of implemented actions
 * @param {Array.<String>} similarActions List of relevant actions
 *
 * @return {GeneratorFunction}
 */
function methodNotAllowed(actionList, similarActions) {
  let methods = intersection(actionList, similarActions).map(
    action => ACTIONS[action].method.toUpperCase()
  );

  return function* middleware(next) {
    this.status = 405;
    this.set('Allow', methods.join(','));
    yield* next;
  };
}

/**
 * A recursive generator function that yields koa-route middlewares for each route.
 *
 * @param {Object} resources Contains all resources and their actions.
 * @param {String} prefix String to prepend to URL when generating routes.
 * @param {String} resourceName Name of the current resource we are processing.
 *
 * @return {Iterable}
 */
function* getMiddlewares(resources, prefix = '', resourceName = '') {

  // If our resources object is null, return
  if (resources === null || typeof resources !== 'object') return;

  // Extract resource keys, and remove any key that starts in an underscore
  const resourceKeys = keysIn(resources).filter(key => key[0] !== '_');

  // Determine if this object has actions as properties
  const actionList = intersection(resourceKeys, keysIn(ACTIONS));
  const hasActions = actionList.length > 0;

  // Iterate through each action if we have at least one action
  if (hasActions) {
    // Check for invariant violations
    if (resourceName === '')
      throw Error('The root resource object cannot contain actions.');

    for (const name in ACTIONS) {
      // Check for invariant violations
      if (typeof resources[name] !== 'undefined' &&
          typeof resources[name] !== 'function')
        throw Error(`Action '${key}' must be a function.`);

      const action = ACTIONS[name];
      yield route[action.method](
        `${prefix}${action.url(resourceName)}`,
        resources[name] || methodNotAllowed(actionList, action.similar)
      );
    }
  }

  // Iterate through the rest of the methods (non-actions)
  for (let index = 0; index < resourceKeys.length; index++) {
    const key = resourceKeys[index];
    if (!includes(keysIn(ACTIONS), key)) {
      let innerPrefix;

      // Determine prefix to send to inner resource
      if (resourceName === '') {
        innerPrefix = prefix;
      } else if (hasActions) {
        innerPrefix = `${prefix}/${resourceName}/:${resourceName}Param`;
      } else {
        innerPrefix = `${prefix}/${resourceName}`;
      }

      // Iterate through inner resources
      yield* getMiddlewares(resources[key], innerPrefix, key);
    }
  }
}

/**
 * Creates the middleware given resources and their actions.
 *
 * @param {Object} resources Contains all resources and their actions.
 *
 * @return {GeneratorFunction} The middleware.
 */
export default function resourceRoutes(resources) {
  // Use koa-compose on all REST middlewares generated by getMiddlewares
  return compose(Array.from(getMiddlewares(resources)));
}
<|endoftext|>


<commit_before>var crypto = require('crypto');

var BLOCK_SIZE = 1 << 14;

var BLOCK_BLANK = 0;
var BLOCK_RESERVED = 1;
var BLOCK_WRITTEN = 2;

var sha1 = function(data) {
	return crypto.createHash('sha1').update(data).digest('hex');
};

var Piece = function(length) {
	if (!(this instanceof Piece)) return new Piece(length);

	this.length = length;
	this.buffer = null;
	this.blocks = null;
	this.blocksWritten = 0;
};

Piece.prototype.__proto__ = process.EventEmitter.prototype;

Piece.prototype.select = function() {
	if (!this.blocks) this.clear();
	for (var i = 0; i < this.blocks.length; i++) {
		if (this.blocks[i]) continue;
		this.blocks[i] = BLOCK_RESERVED;
		return i * BLOCK_SIZE;
	}
	return -1;
};

Piece.prototype.sizeof = function(offset) {
	return Math.min(BLOCK_SIZE, this.length - offset);
};

Piece.prototype.deselect = function(offset) {
	var i = (offset / BLOCK_SIZE) | 0;
	if (!this.blocks) this.clear();
	if (this.blocks[i] === BLOCK_RESERVED) this.blocks[i] = BLOCK_BLANK;
};

Piece.prototype.clear = function() {
	this.blocks = new Uint8Array(Math.ceil(this.length / BLOCK_SIZE));
};

Piece.prototype.write = function(offset, buffer) {
	var i = (offset / BLOCK_SIZE) | 0;
	if (!this.blocks) this.clear();
	if (this.blocks[i] === BLOCK_WRITTEN) return;

	this.buffer = this.buffer || new Buffer(this.length);
	this.blocks[i] = BLOCK_WRITTEN;
	this.blocksWritten++;
	buffer.copy(this.buffer, offset);

	var firstBlank = Math.min( Array.prototype.indexOf.call(this.blocks, BLOCK_BLANK),
							   Array.prototype.indexOf.call(this.blocks, BLOCK_RESERVED) );
	this.emit("progress", Math.min( this.buffer.length,  ( (firstBlank == -1) ? this.blocks.length : firstBlank ) * BLOCK_SIZE));

	return this.blocksWritten === this.blocks.length && this.buffer;
};

Piece.prototype.reset = function() {
	this.buffer = null;
	this.blocks = null;
	this.blocksWritten = 0;
};

module.exports = Piece;
<commit_msg>Progress also exported as a property<commit_after>var crypto = require('crypto');

var BLOCK_SIZE = 1 << 14;

var BLOCK_BLANK = 0;
var BLOCK_RESERVED = 1;
var BLOCK_WRITTEN = 2;

var sha1 = function(data) {
	return crypto.createHash('sha1').update(data).digest('hex');
};

var Piece = function(length) {
	if (!(this instanceof Piece)) return new Piece(length);

	this.length = length;
	this.buffer = null;
	this.blocks = null;
	this.blocksWritten = 0;
	this.progress = 0;
};

Piece.prototype.__proto__ = process.EventEmitter.prototype;

Piece.prototype.select = function() {
	if (!this.blocks) this.clear();
	for (var i = 0; i < this.blocks.length; i++) {
		if (this.blocks[i]) continue;
		this.blocks[i] = BLOCK_RESERVED;
		return i * BLOCK_SIZE;
	}
	return -1;
};

Piece.prototype.sizeof = function(offset) {
	return Math.min(BLOCK_SIZE, this.length - offset);
};

Piece.prototype.deselect = function(offset) {
	var i = (offset / BLOCK_SIZE) | 0;
	if (!this.blocks) this.clear();
	if (this.blocks[i] === BLOCK_RESERVED) this.blocks[i] = BLOCK_BLANK;
};

Piece.prototype.clear = function() {
	this.blocks = new Uint8Array(Math.ceil(this.length / BLOCK_SIZE));
};

Piece.prototype.write = function(offset, buffer) {
	var i = (offset / BLOCK_SIZE) | 0;
	if (!this.blocks) this.clear();
	if (this.blocks[i] === BLOCK_WRITTEN) return;

	this.buffer = this.buffer || new Buffer(this.length);
	this.blocks[i] = BLOCK_WRITTEN;
	this.blocksWritten++;
	buffer.copy(this.buffer, offset);

	var firstBlank = Math.min( Array.prototype.indexOf.call(this.blocks, BLOCK_BLANK),
							   Array.prototype.indexOf.call(this.blocks, BLOCK_RESERVED) );
	this.progress = Math.min( this.buffer.length,  ( (firstBlank == -1) ? this.blocks.length : firstBlank ) * BLOCK_SIZE);
	this.emit("progress", this.progress);

	return this.blocksWritten === this.blocks.length && this.buffer;
};

Piece.prototype.reset = function() {
	this.buffer = null;
	this.blocks = null;
	this.blocksWritten = 0;
};

module.exports = Piece;
<|endoftext|>


<commit_before>/**
 * Install plugin.
 */

import Url from './url/index';
import Http from './http/index';
import Promise from './promise';
import Resource from './resource';
import Util, {options} from './util';

function plugin(Vue) {

    if (plugin.installed) {
        return;
    }

    Util(Vue);

    Vue.url = Url;
    Vue.http = Http;
    Vue.resource = Resource;
    Vue.Promise = Promise;

    Object.defineProperties(Vue.prototype, {

        $url: {
            get() {
                return options(Vue.url, this, this.$options.url);
            }
        },

        $http: {
            get() {
                return options(Vue.http, this, this.$options.http);
            }
        },

        $resource: {
            get() {
                return Vue.resource.bind(this);
            }
        },

        $promise: {
            get() {
                return (executor) => new Vue.Promise(executor, this);
            }
        }

    });
}

if (typeof window !== 'undefined' && window.Vue) {
    window.Vue.use(plugin);
}

export default plugin;
<commit_msg>Add additional check if plugin has already been registered<commit_after>/**
 * Install plugin.
 */

import Url from './url/index';
import Http from './http/index';
import Promise from './promise';
import Resource from './resource';
import Util, {options} from './util';

function plugin(Vue) {

    if (plugin.installed) {
        return;
    }

    Util(Vue);

    Vue.url = Url;
    Vue.http = Http;
    Vue.resource = Resource;
    Vue.Promise = Promise;

    Object.defineProperties(Vue.prototype, {

        $url: {
            get() {
                return options(Vue.url, this, this.$options.url);
            }
        },

        $http: {
            get() {
                return options(Vue.http, this, this.$options.http);
            }
        },

        $resource: {
            get() {
                return Vue.resource.bind(this);
            }
        },

        $promise: {
            get() {
                return (executor) => new Vue.Promise(executor, this);
            }
        }

    });
}

if (typeof window !== 'undefined' && window.Vue && !window.Vue.resource) {
    window.Vue.use(plugin);
}

export default plugin;
<|endoftext|>


<commit_before>import EventEmitter from 'events';

import { setPromisesDependency, getPromisesDependency } from './utils';
import { main, readyFreddy, getEnv, getValue, setValue, apifyClient, call } from './actor';
import { launchPuppeteer } from './puppeteer';
import { browse } from './browser';

/* globals module */

// Publicly available functions
const Apify = {
    main,
    getEnv,
    getValue,
    setValue,
    call,
    readyFreddy,
    setPromisesDependency,
    getPromisesDependency,
    browse,
    launchWebdriver: browse,
    launchPuppeteer,
    client: apifyClient,
    events: new EventEmitter(),
};

/**
 * @module Apify
 * @description
 *

 * The `apify` NPM package simplifies development of acts in Apify Actor -
 * a serverless computing platform that enables execution of arbitrary pieces of code in the cloud.
 * The package provides helper functions to launch web browsers with proxies,
 * access the storage etc. Note that the usage of the package is optional,
 * you can create acts without it.
 *

 *

 * For more information about the Apify Actor platform, please go to
 * {@link https://www.apify.com/docs/actor|Actor documentation}.
 * View the source code on {@link https://github.com/apifier/apify-runtime-js|GitHub}
 *

 *
 *
Example usage

 *
const Apify = require('apify');
 *
 * Apify.main(async () => {
 *   // Get input of the act
 *   const input = await Apify.getValue('INPUT');
 *   console.dir(input);
 *
 *   // Do something useful here...
 *   const browser = await Apify.launchPuppeteer();
 *   const page = await browser.newPage();
 *   await page.goto('http://www.example.com');
 *   const pageTitle = await page.title();
 *
 *   // Save output
 *   await Apify.setValue('OUTPUT', { pageTitle });
 * });

 *
 *
Installation

 *
This package requires Node.js 6 or higher. It might work with lower versions too,
 * but they are neither tested nor supported.
 * The package is primarily used
 *

 *
The package also be used for local development. To install it on your machine,
 * run the following command in your Node.js project:
 * To install the package locally, run the following command:

 * ```bash
 * npm install apify --save
 * ```
 *

 *
Promises vs. callbacks

 *

 * By default, all asynchronous functions return a promise.
 * However, they also accept an optional Node.js-style callback as the last parameter.
 * If the callback is provided, the return value of the functions is not defined
 * and the functions only invoke the callback upon completion or error.
 *

 *

 * To set a promise dependency from an external library,
 * use the Apify.setPromisesDependency() function.
 * If this function is not called, the runtime defaults to
 * native promises if they are available, or it throws an error.
 *

 *
Programmer's reference

 *
The following sections describe all functions and properties provided by the `apify` package.
 * All of them are instance members exported directly by the main module.
 *

 */
module.exports = Apify;
<commit_msg>Updated docs<commit_after>import EventEmitter from 'events';

import { setPromisesDependency, getPromisesDependency } from './utils';
import { main, readyFreddy, getEnv, getValue, setValue, apifyClient, call } from './actor';
import { launchPuppeteer } from './puppeteer';
import { browse } from './browser';

/* globals module */

// Publicly available functions
const Apify = {
    main,
    getEnv,
    getValue,
    setValue,
    call,
    readyFreddy,
    setPromisesDependency,
    getPromisesDependency,
    browse,
    launchWebdriver: browse,
    launchPuppeteer,
    client: apifyClient,
    events: new EventEmitter(),
};

/**
 * @module Apify
 * @description
 *

 * The `apify` NPM package simplifies development of acts in Apify Actor -
 * a serverless computing platform that enables execution of arbitrary pieces of code in the cloud.
 * The package provides helper functions to launch web browsers with proxies,
 * access the storage etc. Note that the usage of the package is optional,
 * you can create acts without it.
 *

 *

 * For more information about the Apify Actor platform, please go to
 * {@link https://www.apify.com/docs/actor|Actor documentation}.
 * The source code of this package is available on {@link https://github.com/apifier/apify-runtime-js|GitHub}.
 *

 *
 *
Example usage

 *
const Apify = require('apify');
 *
 * Apify.main(async () => {
 *   // Get input of the act
 *   const input = await Apify.getValue('INPUT');
 *   console.dir(input);
 *
 *   // Do something useful here...
 *   const browser = await Apify.launchPuppeteer();
 *   const page = await browser.newPage();
 *   await page.goto('http://www.example.com');
 *   const pageTitle = await page.title();
 *
 *   // Save output
 *   await Apify.setValue('OUTPUT', { pageTitle });
 * });

 *
 *
Installation

 *
This package requires Node.js 6 or higher. It might work with lower versions too,
 * but they are neither tested nor supported.
 * To install the package locally, run the following command in your Node.js project:

 * ```bash
 * npm install apify --save
 * ```
 *

 *
Promises vs. callbacks

 *

 * By default, all asynchronous functions provided by this package return a promise.
 * However, most of them also accept an optional Node.js-style callback as the last parameter.
 * If the callback is provided, the return value of the functions is not defined
 * and the functions only invoke the callback upon completion or error.
 *

 *

 * To set a promise dependency from an external library,
 * use the Apify.setPromisesDependency() function.
 * If this function is not called, the runtime defaults to
 * native promises if they are available, or it throws an error.
 *

 *
Programmer's reference

 *
The following sections describe all functions and properties provided by the `apify` package.
 * All of them are instance members exported directly by the main module.
 *

 */
module.exports = Apify;
<|endoftext|>


<commit_before>'use strict';

import React  from 'react';
import moment from 'moment';
import 'moment-timezone';

export default class Moment extends React.Component {

    state = {
        content: ''
    };

    componentWillMount() {
        this.generateContent(this.props);
    }

    componentDidMount() {
        this.interval = global.setInterval(() => {
            this.generateContent(this.props);
        }, 60000);
    }

    componentWillUnmount() {
        clearInterval(this.interval);
    }

    componentWillReceiveProps(nextProps) {
        this.generateContent(nextProps);
    }

    static getDatetime(props) {
        let {
            date,
            parse,
            utc,
            unix,
            tz
        } = props;
        date = date || props.children;

        let datetime = null;

        if (utc) {
            datetime = moment.utc(date, parse);
        } else if (unix) {
            datetime = moment.unix(date);
        } else {
            datetime = moment(date, parse);
        }
        if (tz) {
            datetime = datetime.tz(tz);
        }

        return datetime
    }

    generateContent(props) {
        let {
            format,
            fromNow,
            from,
            toNow,
            to,
            calendar,
            ago
        } = props;

        let datetime = Moment.getDatetime(props);

        let content  = '';
        if (format) {
            content = datetime.format(format);
        } else if (from) {
            content = datetime.from(from, ago);
        } else if (fromNow) {
            content = datetime.fromNow(ago);
        } else if (to) {
            content = datetime.to(to, ago);
        } else if (toNow) {
            content = datetime.toNow(ago);
        } else if (calendar) {
            content = datetime.calendar();
        } else {
            content = datetime.toString();
        }

        this.setState({ content })
    }

    render() {
        let {
            date,
            parse,
            format,
            fromNow,
            from,
            toNow,
            to,
            calendar,
            ago,
            utc,
            unix,
            tz,
            ...other
        } = this.props;
        let datetime = Moment.getDatetime(this.props);
        let {
          content,
        } = this.state;

        return (
            <time dateTime={datetime.format()} {...other}>{content}</time>
        )
    }
}

const dateTypes = [
    React.PropTypes.string,
    React.PropTypes.number,
    React.PropTypes.array,
    React.PropTypes.object
];

const parseTypes = [
    React.PropTypes.string,
    React.PropTypes.array
];

Moment.propTypes = {
    date:       React.PropTypes.oneOfType(dateTypes),
    parse:      React.PropTypes.oneOfType(parseTypes),
    format:     React.PropTypes.string,
    ago:        React.PropTypes.bool,
    fromNow:    React.PropTypes.bool,
    from:       React.PropTypes.oneOfType(dateTypes),
    toNow:      React.PropTypes.bool,
    to:         React.PropTypes.oneOfType(dateTypes),
    calendar:   React.PropTypes.bool,
    unix:       React.PropTypes.bool,
    utc:        React.PropTypes.bool,
    tz:         React.PropTypes.string
};

Moment.defaultProps = {
    fromNow:    false,
    toNow:      false,
    calendar:   false,
    ago:        false,
    unix:       false,
    utc:        false
};
<commit_msg>Add locale support<commit_after>'use strict';

import React  from 'react';
import moment from 'moment';
import 'moment-timezone';

export default class Moment extends React.Component {
    constructor(props) {
      super(props);

      this.state = { content: '' };
    }

    componentWillMount() {
        this.generateContent(this.props);
    }

    componentDidMount() {
        this.interval = global.setInterval(() => {
            this.generateContent(this.props);
        }, 60000);
    }

    componentWillUnmount() {
        clearInterval(this.interval);
    }

    componentWillReceiveProps(nextProps) {
        this.generateContent(nextProps);
    }

    static getDatetime(props) {
        let {
            date,
            locale,
            parse,
            utc,
            unix,
            tz
        } = props;
        date = date || props.children;

        let datetime = null;
        locale = locale ? locale : moment.locale();

        if (utc) {
            datetime = moment.utc(date, parse, locale);
        } else if (unix) {
            // moment#unix fails because of a deprecation,
            // but since moment#unix(s) is implemented as moment(s * 1000),
            // this works equivalently
            datetime = moment(date * 1000, parse, locale);
        } else {
            datetime = moment(date, parse, locale);
        }
        if (tz) {
            datetime = datetime.tz(tz);
        }

        return datetime
    }

    generateContent(props) {
        let {
            format,
            fromNow,
            from,
            toNow,
            to,
            calendar,
            ago
        } = props;

        let datetime = Moment.getDatetime(props);

        let content  = '';
        if (format) {
            content = datetime.format(format);
        } else if (from) {
            content = datetime.from(from, ago);
        } else if (fromNow) {
            content = datetime.fromNow(ago);
        } else if (to) {
            content = datetime.to(to, ago);
        } else if (toNow) {
            content = datetime.toNow(ago);
        } else if (calendar) {
            content = datetime.calendar();
        } else {
            content = datetime.toString();
        }

        this.setState({ content })
    }

    render() {
        let {
            date,
            parse,
            format,
            fromNow,
            from,
            toNow,
            to,
            calendar,
            ago,
            utc,
            unix,
            tz,
            locale,
            ...other
        } = this.props;
        let datetime = Moment.getDatetime(this.props);
        let {
          content,
        } = this.state;

        return (
            <time dateTime={datetime.format()} {...other}>{content}</time>
        )
    }
}

const dateTypes = [
    React.PropTypes.string,
    React.PropTypes.number,
    React.PropTypes.array,
    React.PropTypes.object
];

const parseTypes = [
    React.PropTypes.string,
    React.PropTypes.array
];

Moment.propTypes = {
    date:       React.PropTypes.oneOfType(dateTypes),
    parse:      React.PropTypes.oneOfType(parseTypes),
    format:     React.PropTypes.string,
    ago:        React.PropTypes.bool,
    fromNow:    React.PropTypes.bool,
    from:       React.PropTypes.oneOfType(dateTypes),
    toNow:      React.PropTypes.bool,
    to:         React.PropTypes.oneOfType(dateTypes),
    calendar:   React.PropTypes.bool,
    unix:       React.PropTypes.bool,
    utc:        React.PropTypes.bool,
    tz:         React.PropTypes.string
};

Moment.defaultProps = {
    fromNow:    false,
    toNow:      false,
    calendar:   false,
    ago:        false,
    unix:       false,
    utc:        false
};
<|endoftext|>