<commit_before>let _ = require('./_')
let Bot = require('./bot')
let Human = require('./human')
let Pool = require('./pool')
let Room = require('./room')
let Sock = require('./sock')

let SECOND = 1000
let MINUTE = 1000 * 60
let HOUR   = 1000 * 60 * 60

let games = {}

;(function playerTimer() {
  for (var id in games) {
    var game = games[id]
    if (game.round < 1)
      continue
    for (var p of game.players)
      if (p.time && !--p.time)
        p.pickOnTimeout()
  }
  setTimeout(playerTimer, SECOND)
})()

;(function gameTimer() {
  var now = Date.now()
  for (var id in games)
    if (games[id].expires < now)
      games[id].kill('game over')

  setTimeout(gameTimer, MINUTE)
})()

module.exports = class Game extends Room {
  constructor({id, title, seats, type, sets, cube, isPrivate}) {
    super({isPrivate})

    if (sets) {
      if (type != 'chaos') {
        Object.assign(this, {
          sets,
          format: sets.join(' / ')
        })
      } else {
        this.format = 'CHAOS!'
      }
    } else {
      let format = type
      if (type === 'cube draft')
        format += ' ' + cube.packs + 'x' + cube.cards
      Object.assign(this, { cube, format })
    }

    var gameID = _.id()
    Object.assign(this, { title, seats, type,
      delta: -1,
      hostID: id,
      id: gameID,
      players: [],
      round: 0,
      rounds: cube ? cube.packs : 3
    })
    this.renew()
    games[gameID] = this

    //console.log(`game ${id} created`)
    Game.broadcastGameInfo()
  }

  renew() {
    this.expires = Date.now() + HOUR
  }

  get isActive() {
    return this.players.some(x => x.isActive)
  }

  get didGameStart() {
    return this.round !== 0
  }

  get isGameFinished() {
    return this.round === -1
  }

  get isGameInProgress() {
    return this.didGameStart && !this.isGameFinished
  }

  // The number of total games. This includes ones that have been long since
  // abandoned but not yet garbage-collected by the `renew` mechanism.
  static numGames() {
    return Object.keys(games).length
  }

  // The number of games which have a player still in them.
  static numActiveGames() {
    let count = 0
    for (let id of Object.keys(games)) {
      if (games[id].isActive)
        count++
    }
    return count
  }

  // The number of players in active games.
  static totalNumPlayers() {
    let count = 0
    for (let id of Object.keys(games)) {
      if (games[id].isActive) {
        count += games[id].players.filter(x => x.isConnected && !x.isBot).length
      }
    }
    return count
  }

  static broadcastGameInfo() {
    Sock.broadcast('set', {
      numPlayers: Game.totalNumPlayers(),
      numGames: Game.numGames(),
      numActiveGames: Game.numActiveGames(),
    })
    Game.broadcastRoomInfo()
    //console.log(`there are now ${Game.totalNumPlayers()} total players in ${Game.numGames()} games, ${Game.numActiveGames()} active`)
  }

  static broadcastRoomInfo() {
    let roomInfo = []
    for (let id of Object.keys(games)) {
      let game = games[id]
      if (game.isPrivate || game.didGameStart || !game.isActive)
        continue

      let usedSeats = game.players.length
      let totalSeats = game.seats
      if (usedSeats === totalSeats)
        continue

      roomInfo.push({
        id: game.id,
        title: game.title,
        usedSeats,
        totalSeats,
        name: game.name,
        format: game.format,
        timeCreated: game.timeCreated,
      })
    }
    Sock.broadcast('set', { roomInfo: roomInfo })
  }

  name(name, sock) {
    super(name, sock)
    sock.h.name = sock.name
    this.meta()
  }

  join(sock) {
    for (var i = 0; i < this.players.length; i++) {
      var p = this.players[i]
      if (p.id === sock.id) {
        p.attach(sock)
        this.greet(p)
        this.meta()
        super(sock)
        return
      }
    }

    if (this.didGameStart)
      return sock.err('game already started')

    super(sock)

    var h = new Human(sock)
    if (h.id === this.hostID) {
      h.isHost = true
      sock.once('start', this.start.bind(this))
      sock.on('kick', this.kick.bind(this))
    }
    h.on('meta', this.meta.bind(this))
    this.players.push(h)
    this.greet(h)
    this.meta()
  }

  kick(i) {
    let h = this.players[i]
    if (!h || h.isBot)
      return

    if (this.didGameStart)
      h.kick()
    else
      h.exit()

    h.err('you were kicked')
    h.kick()
  }

  greet(h) {
    h.isConnected = true
    h.send('set', {
      isHost: h.isHost,
      round: this.round,
      self: this.players.indexOf(h),
      format: this.format,
    })
  }

  exit(sock) {
    if (this.didGameStart)
      return

    sock.removeAllListeners('start')
    var index = this.players.indexOf(sock.h)
    this.players.splice(index, 1)

    this.players.forEach((p, i) =>
      p.send('set', { self: i }))
    this.meta()
  }

  meta(state={}) {
    state.players = this.players.map(p => ({
      hash: p.hash,
      name: p.name,
      time: p.time,
      packs: p.packs.length,
      isBot: p.isBot,
      isConnected: p.isConnected,
      isReadyToStart: p.isReadyToStart,
    }))
    for (var p of this.players)
      p.send('set', state)
    Game.broadcastGameInfo()
  }

  kill(msg) {
    if (!this.isGameFinished)
      this.players.forEach(p => p.err(msg))

    delete games[this.id]
    //console.log(`game ${this.id} destroyed`)
    Game.broadcastGameInfo()

    this.emit('kill')
  }

  end() {
    var humans = 0
    for (var p of this.players)
        if (!p.isBot)
            humans++

    var draftcap = {
      "gameID": this.id,
      "players": humans,
      "type": this.type,
      "sets": this.sets,
      "seats": this.seats,
      "time": Date.now(),
      "cap": []
    }
    var seatnumber = 0
    for (var p of this.players) {
      seatnumber++
      var playercap = {
        "id": p.id,
        "name": p.name,
         "ip": p.ip,
        "seat": seatnumber,
        "picks": p.cap.packs
      }
      draftcap.cap.push(playercap)
    }
    var jsonfile = require('jsonfile')
    var file = './data/cap.json'
    jsonfile.writeFile(file, draftcap, {flag: 'a'}, function (err) {
      if (err) console.error(err)})

    this.renew()
    this.round = -1
    this.meta({ round: -1 })
  }

  pass(p, pack) {
    if (!pack.length) {
      if (!--this.packCount)
        this.startRound()
      else
        this.meta()
      return
    }

    var index = this.players.indexOf(p) + this.delta
    var p2 = _.at(this.players, index)
    p2.getPack(pack)
    if (!p2.isBot)
      this.meta()
  }

  startRound() {
    if (this.round != 0) {
        for (var p of this.players) {
            p.cap.packs[this.round] = p.picks
            //console.log('moving ' + p.name + ' picks ' + p.picks + ' to cap')
            p.picks = []
        }
    }
    if (this.round++ === this.rounds)
      return this.end()

    var {players} = this
    this.packCount = players.length
    this.delta *= -1

    for (var p of players)
      if (!p.isBot)
        p.getPack(this.pool.pop())

    //let the bots play
    this.meta = ()=>{}
    var index = players.findIndex(p => !p.isBot)
    var count = players.length
    while (--count) {
      index -= this.delta
      p = _.at(players, index)
      if (p.isBot)
        p.getPack(this.pool.pop())
    }
    this.meta = Game.prototype.meta
    this.meta({ round: this.round })
  }

  hash(h, deck) {
    h.hash = hash(deck)
    this.meta()
  }

  start({addBots, useTimer, timerLength}) {
    var src = this.cube ? this.cube : this.sets
    var {players} = this
    var p

    if (!players.every(x => x.isReadyToStart))
      return

    this.renew()

    if (/sealed/.test(this.type)) {
      this.round = -1
      var pools = Pool(src, players.length, true)
      for (p of players) {
        p.pool = pools.pop()
        p.send('pool', p.pool)
        p.send('set', { round: -1 })
      }
      console.log(`${this.type} using ${this.format} game ${this.id} started with ${this.players.length} players`)
      Game.broadcastGameInfo()
      return
    }

    for (p of players) {
      p.useTimer = useTimer
      p.timerLength = timerLength
    }

    console.log(`${this.type} using ${this.format} game ${this.id} started with ${this.players.length} players and ${this.seats} seats`)
    Game.broadcastGameInfo()
    if (addBots)
      while (players.length < this.seats)
        players.push(new Bot)
    _.shuffle(players)

    if (/chaos/.test(this.type))
      this.pool = Pool(src, players.length, true, true)
    else
      this.pool = Pool(src, players.length)

    players.forEach((p, i) => {
      p.on('pass', this.pass.bind(this, p))
      p.send('set', { self: i })
    })
    this.startRound()
  }
}
<commit_msg>Revert bot draftcap<commit_after>let _ = require('./_')
let Bot = require('./bot')
let Human = require('./human')
let Pool = require('./pool')
let Room = require('./room')
let Sock = require('./sock')

let SECOND = 1000
let MINUTE = 1000 * 60
let HOUR   = 1000 * 60 * 60

let games = {}

;(function playerTimer() {
  for (var id in games) {
    var game = games[id]
    if (game.round < 1)
      continue
    for (var p of game.players)
      if (p.time && !--p.time)
        p.pickOnTimeout()
  }
  setTimeout(playerTimer, SECOND)
})()

;(function gameTimer() {
  var now = Date.now()
  for (var id in games)
    if (games[id].expires < now)
      games[id].kill('game over')

  setTimeout(gameTimer, MINUTE)
})()

module.exports = class Game extends Room {
  constructor({id, title, seats, type, sets, cube, isPrivate}) {
    super({isPrivate})

    if (sets) {
      if (type != 'chaos') {
        Object.assign(this, {
          sets,
          format: sets.join(' / ')
        })
      } else {
        this.format = 'CHAOS!'
      }
    } else {
      let format = type
      if (type === 'cube draft')
        format += ' ' + cube.packs + 'x' + cube.cards
      Object.assign(this, { cube, format })
    }

    var gameID = _.id()
    Object.assign(this, { title, seats, type,
      delta: -1,
      hostID: id,
      id: gameID,
      players: [],
      round: 0,
      rounds: cube ? cube.packs : 3
    })
    this.renew()
    games[gameID] = this

    //console.log(`game ${id} created`)
    Game.broadcastGameInfo()
  }

  renew() {
    this.expires = Date.now() + HOUR
  }

  get isActive() {
    return this.players.some(x => x.isActive)
  }

  get didGameStart() {
    return this.round !== 0
  }

  get isGameFinished() {
    return this.round === -1
  }

  get isGameInProgress() {
    return this.didGameStart && !this.isGameFinished
  }

  // The number of total games. This includes ones that have been long since
  // abandoned but not yet garbage-collected by the `renew` mechanism.
  static numGames() {
    return Object.keys(games).length
  }

  // The number of games which have a player still in them.
  static numActiveGames() {
    let count = 0
    for (let id of Object.keys(games)) {
      if (games[id].isActive)
        count++
    }
    return count
  }

  // The number of players in active games.
  static totalNumPlayers() {
    let count = 0
    for (let id of Object.keys(games)) {
      if (games[id].isActive) {
        count += games[id].players.filter(x => x.isConnected && !x.isBot).length
      }
    }
    return count
  }

  static broadcastGameInfo() {
    Sock.broadcast('set', {
      numPlayers: Game.totalNumPlayers(),
      numGames: Game.numGames(),
      numActiveGames: Game.numActiveGames(),
    })
    Game.broadcastRoomInfo()
    //console.log(`there are now ${Game.totalNumPlayers()} total players in ${Game.numGames()} games, ${Game.numActiveGames()} active`)
  }

  static broadcastRoomInfo() {
    let roomInfo = []
    for (let id of Object.keys(games)) {
      let game = games[id]
      if (game.isPrivate || game.didGameStart || !game.isActive)
        continue

      let usedSeats = game.players.length
      let totalSeats = game.seats
      if (usedSeats === totalSeats)
        continue

      roomInfo.push({
        id: game.id,
        title: game.title,
        usedSeats,
        totalSeats,
        name: game.name,
        format: game.format,
        timeCreated: game.timeCreated,
      })
    }
    Sock.broadcast('set', { roomInfo: roomInfo })
  }

  name(name, sock) {
    super(name, sock)
    sock.h.name = sock.name
    this.meta()
  }

  join(sock) {
    for (var i = 0; i < this.players.length; i++) {
      var p = this.players[i]
      if (p.id === sock.id) {
        p.attach(sock)
        this.greet(p)
        this.meta()
        super(sock)
        return
      }
    }

    if (this.didGameStart)
      return sock.err('game already started')

    super(sock)

    var h = new Human(sock)
    if (h.id === this.hostID) {
      h.isHost = true
      sock.once('start', this.start.bind(this))
      sock.on('kick', this.kick.bind(this))
    }
    h.on('meta', this.meta.bind(this))
    this.players.push(h)
    this.greet(h)
    this.meta()
  }

  kick(i) {
    let h = this.players[i]
    if (!h || h.isBot)
      return

    if (this.didGameStart)
      h.kick()
    else
      h.exit()

    h.err('you were kicked')
    h.kick()
  }

  greet(h) {
    h.isConnected = true
    h.send('set', {
      isHost: h.isHost,
      round: this.round,
      self: this.players.indexOf(h),
      format: this.format,
    })
  }

  exit(sock) {
    if (this.didGameStart)
      return

    sock.removeAllListeners('start')
    var index = this.players.indexOf(sock.h)
    this.players.splice(index, 1)

    this.players.forEach((p, i) =>
      p.send('set', { self: i }))
    this.meta()
  }

  meta(state={}) {
    state.players = this.players.map(p => ({
      hash: p.hash,
      name: p.name,
      time: p.time,
      packs: p.packs.length,
      isBot: p.isBot,
      isConnected: p.isConnected,
      isReadyToStart: p.isReadyToStart,
    }))
    for (var p of this.players)
      p.send('set', state)
    Game.broadcastGameInfo()
  }

  kill(msg) {
    if (!this.isGameFinished)
      this.players.forEach(p => p.err(msg))

    delete games[this.id]
    //console.log(`game ${this.id} destroyed`)
    Game.broadcastGameInfo()

    this.emit('kill')
  }

  end() {
    var humans = 0
    for (var p of this.players)
        if (!p.isBot)
            humans++

    var draftcap = {
      "gameID": this.id,
      "players": humans,
      "type": this.type,
      "sets": this.sets,
      "seats": this.seats,
      "time": Date.now(),
      "cap": []
    }
    var seatnumber = 0
    for (var p of this.players) {
      seatnumber++
      if (!p.isBot) {
        var playercap = {
          "id": p.id,
          "name": p.name,
          "ip": p.ip,
          "seat": seatnumber,
          "picks": p.cap.packs
        }
        draftcap.cap.push(playercap)
      }
      else {
        playercap = {
          "bot": true,
          "seat": seatnumber,
          "picks": p.cap.packs
        }
        draftcap.cap.push(playercap)
      }
    }
    var jsonfile = require('jsonfile')
    var file = './data/cap.json'
    jsonfile.writeFile(file, draftcap, {flag: 'a'}, function (err) {
      if (err) console.error(err)})

    this.renew()
    this.round = -1
    this.meta({ round: -1 })
  }

  pass(p, pack) {
    if (!pack.length) {
      if (!--this.packCount)
        this.startRound()
      else
        this.meta()
      return
    }

    var index = this.players.indexOf(p) + this.delta
    var p2 = _.at(this.players, index)
    p2.getPack(pack)
    if (!p2.isBot)
      this.meta()
  }

  startRound() {
    if (this.round != 0) {
        for (var p of this.players) {
            p.cap.packs[this.round] = p.picks
            //console.log('moving ' + p.name + ' picks ' + p.picks + ' to cap')
            p.picks = []
        }
    }
    if (this.round++ === this.rounds)
      return this.end()

    var {players} = this
    this.packCount = players.length
    this.delta *= -1

    for (var p of players)
      if (!p.isBot)
        p.getPack(this.pool.pop())

    //let the bots play
    this.meta = ()=>{}
    var index = players.findIndex(p => !p.isBot)
    var count = players.length
    while (--count) {
      index -= this.delta
      p = _.at(players, index)
      if (p.isBot)
        p.getPack(this.pool.pop())
    }
    this.meta = Game.prototype.meta
    this.meta({ round: this.round })
  }

  hash(h, deck) {
    h.hash = hash(deck)
    this.meta()
  }

  start({addBots, useTimer, timerLength}) {
    var src = this.cube ? this.cube : this.sets
    var {players} = this
    var p

    if (!players.every(x => x.isReadyToStart))
      return

    this.renew()

    if (/sealed/.test(this.type)) {
      this.round = -1
      var pools = Pool(src, players.length, true)
      for (p of players) {
        p.pool = pools.pop()
        p.send('pool', p.pool)
        p.send('set', { round: -1 })
      }
      console.log(`${this.type} using ${this.format} game ${this.id} started with ${this.players.length} players`)
      Game.broadcastGameInfo()
      return
    }

    for (p of players) {
      p.useTimer = useTimer
      p.timerLength = timerLength
    }

    console.log(`${this.type} using ${this.format} game ${this.id} started with ${this.players.length} players and ${this.seats} seats`)
    Game.broadcastGameInfo()
    if (addBots)
      while (players.length < this.seats)
        players.push(new Bot)
    _.shuffle(players)

    if (/chaos/.test(this.type))
      this.pool = Pool(src, players.length, true, true)
    else
      this.pool = Pool(src, players.length)

    players.forEach((p, i) => {
      p.on('pass', this.pass.bind(this, p))
      p.send('set', { self: i })
    })
    this.startRound()
  }
}
<|endoftext|>


<commit_before>'use strict'

import _ from 'lodash'
import jsonPath from 'jsonpath'
import Chance from 'chance'
import fs from 'fs'
import glob from 'glob'

let hazy = {}

//    ___             __ _
//   / __\___  _ __  / _(_) __ _
//  / /  / _ \| '_ \| |_| |/ _` |
// / /__| (_) | | | |  _| | (_| |
// \____/\___/|_| |_|_| |_|\__, |
//                         |___/

hazy.config = {
  seed: null,
  lazy: true,
  debug: false,
  matcher: {
    use: true
  },
  errors: {
    quiet: false,
    soft: false
  }
}

hazy.meta = {
  random: {
    types: {
      basic  : ['bool', 'character', 'integer', 'natural', 'string'],
      text   : ['paragraph', 'sentence', 'syllable', 'word'],
      person : ['age', 'birthday', 'cpf', 'first', 'gender', 'last', 'name', 'prefix', 'ssn', 'suffix'],
      mobile : ['android_id', 'apple_token', 'bb_pin', 'wp7_anid', 'wp8_anid2'],
      web    : ['color', 'domain', 'email', 'fbid', 'google_analytics', 'hashtag', 'ip', 'ipv6', 'klout', 'tld', 'twitter', 'url'],
      geo    : ['address', 'altitude', 'areacode', 'city', 'coordinates', 'country', 'depth', 'geohash', 'latitude', 'longitude', 'phone', 'postal', 'province', 'state', 'street', 'zip'],
      time   : ['ampm', 'date', 'hammertime', 'hour', 'millisecond', 'minute', 'month', 'second', 'timestamp', 'year'],
      misc   : ['guid', 'hash', 'normal', 'radio', 'tv']
    } // TODO - support n, unique and weighted! very useful
  }
}

//    __
//   / /  __ _ _ __   __ _
//  / /  / _` | '_ \ / _` |
// / /__| (_| | | | | (_| |
// \____/\__,_|_| |_|\__, |
//                   |___/

hazy.lang = {
  expression: {
    first : /\|(:|~|>|_|\*|\+)(.*?)?\|/,
    all   : /\|(:|~|>|_|\*|\+)(.*?)?\|/g
  },

  tokens: {
    // expression start/end
    '|': (prev, next) => {
      const isNextTokenEnd = /\|/.test(next)

      if (isNextTokenEnd) {
        throw hazy.lang.exception('Cannot define an empty expression')
      }

      if (!next) {
        // TODO - return a special value saying that this is the end of the token expression sequence. currenlty not technically needed
      }
    },

    // property separator / accessor
    ':': (prev, next) => { // property accessor
      if (!prev) {
        throw hazy.lang.exception('Syntax error, : requires a left operand')
      }

      return prev[next]
    },

    // random data
    '~': (prev, next) => {
      const randProp   = next.split(':')[0],
            randVal    = next.split(':')[1],
            canUseProp = hazy.random.hasOwnProperty(randProp)

      if (canUseProp) {
        const randObjByProp  = hazy.random[randProp],
              randObjSubType = randVal // get property of random operator following ":"

        if (!randObjByProp || !randObjByProp[randObjSubType]) {
          throw hazy.lang.exception('Invalid random data type "' + randObjSubType + '". Supported:', hazy.meta.random.types[randProp])
        }

        return randObjByProp[randObjSubType]()
      } else {
        throw hazy.lang.exception('Invalid random data category "' + randProp + '". Supported', hazy.meta.random.types)
      }
    },

    // embed fixture from the pool
    '+': (prev, next) => hazy.fixture.get(next.trim()),
    // '@': (prev, next) => hazy.fixture.get(next.trim()),

    // query and embed fixture from the pool
    '*': (prev, next) => hazy.fixture.query(next.trim()),

    // embed fixture from the filesystem
    '>': (prev, next) => hazy.fixture.load(next.trim()),

    // find and embed fixture from filesystem or pool
    '_': (prev, next) => hazy.fixture.find(next.trim()),

    // TODO - embed fixture from a remote URL ("@")

    validate: (token) => hazy.lang.tokens.hasOwnProperty(token),

    process: (token, prev, next, rest) => _.bindKey(hazy.lang.tokens, token, prev, next, rest)()
  },

  // extracts tokens from strs and evaluates them. interpolates strings, ignores and simply returns other data types
  process: (str) => {
    const matches = str.split(hazy.lang.expression.all),
          tokens  = []

    _.forEach(matches, (match, i) => {
      const isToken = hazy.lang.tokens.validate(match)

      if (isToken) {
        const prevMatch   = matches[i - 1],
              nextMatch   = matches[i + 1],
              restMatches = _.drop(matches, i + 1),
              tokenResult = hazy.lang.tokens.process(match, prevMatch, nextMatch, restMatches)

        if (tokenResult) {
          // if processed token result is a string, substitute original string as we iterate
          if (_.isString(tokenResult)) {
            str = str.replace(hazy.lang.expression.first, tokenResult)
          } else {
            tokens.push(tokenResult)
          }
        }
      }
    }, this)

    if (!_.isEmpty(tokens)) {
      return _.reduce(tokens) || str
    }

    return str
  },

  exception: (msg) => new Error('[Hazy syntax error] ' + msg)
}

//    ___ _      _
//   / __(_)_  _| |_ _   _ _ __ ___  ___
//  / _\ | \ \/ / __| | | | '__/ _ \/ __|
// / /   | |>  <| |_| |_| | | |  __/\__ \
// \/    |_/_/\_\\__|\__,_|_|  \___||___/
//

hazy.fixture = {
  pool: {},

  // fetches a fixture from the pool and processes it if necessary
  get: (key) => {
    const fixture = hazy.fixture.pool[key]

    if (hazy.config.matcher.use) {
      return hazy.matcher.processDeep(fixture)
    }

    return fixture
  },

  // lazily acquires a fixture from the pool, processing it only once
  lazyGet: _.memoize(key => hazy.fixture.get(key)),

  // attempts to get a fixture from the pool. if that fails, the fixture is searched for on the file system.
  find: (key) => hazy.fixture.get(key) || hazy.fixture.load(`${key}.json`),

  // lazily finds a fixture, processing it only once
  lazyFind: _.memoize(key => hazy.fixture.find(key)),

  // fetches all fixtures from the pool and processes them if necessary
  all: () => _.map(hazy.fixture.pool, (fixture, name) => hazy.fixture.get(name)),

  // registers a processable fixture into the fixture pool
  register: (name, fixture) => {
    hazy.fixture.pool[name] = hazy.fixture.process(fixture) // FIXME - wrap with a special lazy object opposed to just wrapping with a function, too ambiguous
  },

  // registers an array of processable fixtures into the fixture pool
  registerAll: (fixtureMap) => {
    if (_.isObject(fixtureMap)) {
      _.each(fixtureMap, (fixture, name) => hazy.fixture.register(name, fixture))
    } else {
      throw new Error('Fixture map following {name: fixture} must be provided')
    }
  },

   // dynamically process fixture values by type (object, string, array, or function)
  process: (fixture, match) => {
    const processedFixture = fixture

    if (_.isPlainObject(fixture)) {
      _.forEach(fixture, (value, key) => {
        const processedKey = hazy.lang.process(key),
              nextFixture  = value

        processedFixture[processedKey] = hazy.fixture.process(nextFixture)
      })
    }

    if (_.isString(fixture)) {
      return hazy.lang.process(fixture)
    }

    if (_.isArray(fixture)) {
      return fixture.map(hazy.fixture.process)
    }

    if (hazy.config.matcher.use && match) {
      return hazy.matcher.processDeep(processedFixture)
    }

    return processedFixture
  },

  // processes each fixture in the array
  processAll: (fixtures) => fixtures.map(fixture => hazy.fixture.process(fixture)),

  // queries the fixture pool for anything that matches the jsonpath pattern and processes it
  query: (pattern, match) => hazy.matcher.search(pattern, match),

  // load and register a fixture from files matching a glob pattern
  // TODO - support root path configuration
  load: (pattern, options, key) => {
    glob(pattern, options, (err, files) => {
      if (err) {
        throw new Error('Failed to load file')
      }

      _.forEach(files, (file) => {
        const fixtureKey = key instanceof Function ? key(file.name) : file.name

        hazy.fixture.register(fixtureKey, JSON.parse(file))
      })
    })
  },

  // removes a fixture by name from the pool
  remove: (name) => {
    delete hazy.fixture.pool[name]
  },

  // removes all fixtures from the pool
  removeAll: () => {
    hazy.fixture.pool = {}
  }
}

//               _       _
//   /\/\   __ _| |_ ___| |__   ___ _ __ ___
//  /    \ / _` | __/ __| '_ \ / _ \ '__/ __|
// / /\/\ \ (_| | || (__| | | |  __/ |  \__ \
// \/    \/\__,_|\__\___|_| |_|\___|_|  |___/
//

hazy.matcher = {
  // source of all fixture matchers
  pool: {},

  // registers a fixture pattern with a value into the matcher pool
  register: (path, value) => {
    hazy.matcher.pool[path] = value
  },

  // registers a fixture pattern with an advanced config into the matcher pool
  config: (config) => {
    const matcherPath    = config.path,
          matcherHandler = config.handle

    if (hazy.matcher.pool[matcherPath]) {
      delete hazy.matcher.pool[matcherPath]
    }

    hazy.matcher.pool[matcherPath] = {path: matcherPath, handle: matcherHandler}
  },

  // provides a map of all matched patterns in a fixture (pattern as key)
  matches: (fixture) => {
    let matches = {}

    if (hazy.config.matcher.use) {
      _.forEach(hazy.matcher.pool, (v, pattern) => {
        if (_.isObject(fixture)) {
          const jpMatches = jsonPath.query(fixture, pattern)

          if (!_.isEmpty(jpMatches)) {
            matches[pattern] = jpMatches
          }
        }
      })
    } else {
      // WARN - matching disabled
    }

    return matches
  },

  // determines if any matches in the pool apply to the fixture
  hasMatch: (fixture) => !_.isEmpty(
    hazy.matcher.matches(fixture)
  ),

  // search the fixture pool for fixtures matching a specific pattern (intentionally non-lazy- prone to recursion hell and there's also little benefit in evaluating random values)
  search: (pattern, process) => {
    const fixtures = _.values(hazy.fixture.pool)

    return _(fixtures)
      .map(fixture => {
        const jpMatches = jsonPath.query(fixture, pattern)

        if (!_.isEmpty(jpMatches)) {
          // process functional matches if desired
          if (_.isUndefined(process) ? hazy.config.matcher.use : process) {
            return hazy.matcher.process(pattern, fixture)
          }

          return fixture
        }
      })
      .reject(_.isUndefined)
      .value()
  },

  // executes a single pattern matcher handle on a fixture.
  // passive. does not consider non-matching patterns an error unless the matcher is corrupt
  process: (pattern, fixture) => {
    const matcher = hazy.matcher.pool[pattern]

    if (matcher) {
      if (_.isObject(matcher) && _.isFunction(matcher.handle)) {
        const matches = jsonPath.query(fixture, pattern)

        return matcher.handle(fixture, matches, pattern)
      } else {
        throw 'Match pattern does not apply to fixture or handle is not a function'
      }
    }

    return fixture
  },

  // executes handles for all pattern matches on a fixture
  processDeep: (fixture) => {
    const patternMatches = hazy.matcher.matches(fixture)
    let processedFixture = fixture

    _.forEach(patternMatches, (match, pattern) => {
      processedFixture = hazy.matcher.process(pattern, fixture) || processedFixture
    })

    return processedFixture
  }

}

//    __                 _
//   /__\ __ _ _ __   __| | ___  _ __ ___
//  / \/// _` | '_ \ / _` |/ _ \| '_ ` _ \
// / _  \ (_| | | | | (_| | (_) | | | | | |
// \/ \_/\__,_|_| |_|\__,_|\___/|_| |_| |_|
//

hazy.random = _.mapValues(hazy.meta.random.types, (value, key) => {
  let hazyRandObj = {}

  _.forEach(value, v => {
     hazyRandObj[v] = () => new Chance()[v]()
  })

  return hazyRandObj
})

//    ___       _ _     _
//   / __\_   _(_) | __| |
//  /__\// | | | | |/ _` |
// / \/  \ |_| | | | (_| |
// \_____/\__,_|_|_|\__,_|
//

// creates a clone of the current hazy object (shallow, new memory references)
hazy.fork = () => _.clone(hazy, false)

// convenience reference to lodash so that developers don't have to explicitly import the lib in their own code
hazy.util = _

// make the module accessible
module.exports = hazy
<commit_msg>old comment<commit_after>'use strict'

import _ from 'lodash'
import jsonPath from 'jsonpath'
import Chance from 'chance'
import fs from 'fs'
import glob from 'glob'

let hazy = {}

//    ___             __ _
//   / __\___  _ __  / _(_) __ _
//  / /  / _ \| '_ \| |_| |/ _` |
// / /__| (_) | | | |  _| | (_| |
// \____/\___/|_| |_|_| |_|\__, |
//                         |___/

hazy.config = {
  seed: null,
  lazy: true,
  debug: false,
  matcher: {
    use: true
  },
  errors: {
    quiet: false,
    soft: false
  }
}

hazy.meta = {
  random: {
    types: {
      basic  : ['bool', 'character', 'integer', 'natural', 'string'],
      text   : ['paragraph', 'sentence', 'syllable', 'word'],
      person : ['age', 'birthday', 'cpf', 'first', 'gender', 'last', 'name', 'prefix', 'ssn', 'suffix'],
      mobile : ['android_id', 'apple_token', 'bb_pin', 'wp7_anid', 'wp8_anid2'],
      web    : ['color', 'domain', 'email', 'fbid', 'google_analytics', 'hashtag', 'ip', 'ipv6', 'klout', 'tld', 'twitter', 'url'],
      geo    : ['address', 'altitude', 'areacode', 'city', 'coordinates', 'country', 'depth', 'geohash', 'latitude', 'longitude', 'phone', 'postal', 'province', 'state', 'street', 'zip'],
      time   : ['ampm', 'date', 'hammertime', 'hour', 'millisecond', 'minute', 'month', 'second', 'timestamp', 'year'],
      misc   : ['guid', 'hash', 'normal', 'radio', 'tv']
    } // TODO - support n, unique and weighted! very useful
  }
}

//    __
//   / /  __ _ _ __   __ _
//  / /  / _` | '_ \ / _` |
// / /__| (_| | | | | (_| |
// \____/\__,_|_| |_|\__, |
//                   |___/

hazy.lang = {
  expression: {
    first : /\|(:|~|>|_|\*|\+)(.*?)?\|/,
    all   : /\|(:|~|>|_|\*|\+)(.*?)?\|/g
  },

  tokens: {
    // expression start/end
    '|': (prev, next) => {
      const isNextTokenEnd = /\|/.test(next)

      if (isNextTokenEnd) {
        throw hazy.lang.exception('Cannot define an empty expression')
      }

      if (!next) {
        // TODO - return a special value saying that this is the end of the token expression sequence. currenlty not technically needed
      }
    },

    // property separator / accessor
    ':': (prev, next) => { // property accessor
      if (!prev) {
        throw hazy.lang.exception('Syntax error, : requires a left operand')
      }

      return prev[next]
    },

    // random data
    '~': (prev, next) => {
      const randProp   = next.split(':')[0],
            randVal    = next.split(':')[1],
            canUseProp = hazy.random.hasOwnProperty(randProp)

      if (canUseProp) {
        const randObjByProp  = hazy.random[randProp],
              randObjSubType = randVal // get property of random operator following ":"

        if (!randObjByProp || !randObjByProp[randObjSubType]) {
          throw hazy.lang.exception('Invalid random data type "' + randObjSubType + '". Supported:', hazy.meta.random.types[randProp])
        }

        return randObjByProp[randObjSubType]()
      } else {
        throw hazy.lang.exception('Invalid random data category "' + randProp + '". Supported', hazy.meta.random.types)
      }
    },

    // embed fixture from the pool
    '+': (prev, next) => hazy.fixture.get(next.trim()),

    // query and embed fixture from the pool
    '*': (prev, next) => hazy.fixture.query(next.trim()),

    // embed fixture from the filesystem
    '>': (prev, next) => hazy.fixture.load(next.trim()),

    // find and embed fixture from filesystem or pool
    '_': (prev, next) => hazy.fixture.find(next.trim()),

    // TODO - embed fixture from a remote URL ("@")

    validate: (token) => hazy.lang.tokens.hasOwnProperty(token),

    process: (token, prev, next, rest) => _.bindKey(hazy.lang.tokens, token, prev, next, rest)()
  },

  // extracts tokens from strs and evaluates them. interpolates strings, ignores and simply returns other data types
  process: (str) => {
    const matches = str.split(hazy.lang.expression.all),
          tokens  = []

    _.forEach(matches, (match, i) => {
      const isToken = hazy.lang.tokens.validate(match)

      if (isToken) {
        const prevMatch   = matches[i - 1],
              nextMatch   = matches[i + 1],
              restMatches = _.drop(matches, i + 1),
              tokenResult = hazy.lang.tokens.process(match, prevMatch, nextMatch, restMatches)

        if (tokenResult) {
          // if processed token result is a string, substitute original string as we iterate
          if (_.isString(tokenResult)) {
            str = str.replace(hazy.lang.expression.first, tokenResult)
          } else {
            tokens.push(tokenResult)
          }
        }
      }
    }, this)

    if (!_.isEmpty(tokens)) {
      return _.reduce(tokens) || str
    }

    return str
  },

  exception: (msg) => new Error('[Hazy syntax error] ' + msg)
}

//    ___ _      _
//   / __(_)_  _| |_ _   _ _ __ ___  ___
//  / _\ | \ \/ / __| | | | '__/ _ \/ __|
// / /   | |>  <| |_| |_| | | |  __/\__ \
// \/    |_/_/\_\\__|\__,_|_|  \___||___/
//

hazy.fixture = {
  pool: {},

  // fetches a fixture from the pool and processes it if necessary
  get: (key) => {
    const fixture = hazy.fixture.pool[key]

    if (hazy.config.matcher.use) {
      return hazy.matcher.processDeep(fixture)
    }

    return fixture
  },

  // lazily acquires a fixture from the pool, processing it only once
  lazyGet: _.memoize(key => hazy.fixture.get(key)),

  // attempts to get a fixture from the pool. if that fails, the fixture is searched for on the file system.
  find: (key) => hazy.fixture.get(key) || hazy.fixture.load(`${key}.json`),

  // lazily finds a fixture, processing it only once
  lazyFind: _.memoize(key => hazy.fixture.find(key)),

  // fetches all fixtures from the pool and processes them if necessary
  all: () => _.map(hazy.fixture.pool, (fixture, name) => hazy.fixture.get(name)),

  // registers a processable fixture into the fixture pool
  register: (name, fixture) => {
    hazy.fixture.pool[name] = hazy.fixture.process(fixture) // FIXME - wrap with a special lazy object opposed to just wrapping with a function, too ambiguous
  },

  // registers an array of processable fixtures into the fixture pool
  registerAll: (fixtureMap) => {
    if (_.isObject(fixtureMap)) {
      _.each(fixtureMap, (fixture, name) => hazy.fixture.register(name, fixture))
    } else {
      throw new Error('Fixture map following {name: fixture} must be provided')
    }
  },

   // dynamically process fixture values by type (object, string, array, or function)
  process: (fixture, match) => {
    const processedFixture = fixture

    if (_.isPlainObject(fixture)) {
      _.forEach(fixture, (value, key) => {
        const processedKey = hazy.lang.process(key),
              nextFixture  = value

        processedFixture[processedKey] = hazy.fixture.process(nextFixture)
      })
    }

    if (_.isString(fixture)) {
      return hazy.lang.process(fixture)
    }

    if (_.isArray(fixture)) {
      return fixture.map(hazy.fixture.process)
    }

    if (hazy.config.matcher.use && match) {
      return hazy.matcher.processDeep(processedFixture)
    }

    return processedFixture
  },

  // processes each fixture in the array
  processAll: (fixtures) => fixtures.map(fixture => hazy.fixture.process(fixture)),

  // queries the fixture pool for anything that matches the jsonpath pattern and processes it
  query: (pattern, match) => hazy.matcher.search(pattern, match),

  // load and register a fixture from files matching a glob pattern
  // TODO - support root path configuration
  load: (pattern, options, key) => {
    glob(pattern, options, (err, files) => {
      if (err) {
        throw new Error('Failed to load file')
      }

      _.forEach(files, (file) => {
        const fixtureKey = key instanceof Function ? key(file.name) : file.name

        hazy.fixture.register(fixtureKey, JSON.parse(file))
      })
    })
  },

  // removes a fixture by name from the pool
  remove: (name) => {
    delete hazy.fixture.pool[name]
  },

  // removes all fixtures from the pool
  removeAll: () => {
    hazy.fixture.pool = {}
  }
}

//               _       _
//   /\/\   __ _| |_ ___| |__   ___ _ __ ___
//  /    \ / _` | __/ __| '_ \ / _ \ '__/ __|
// / /\/\ \ (_| | || (__| | | |  __/ |  \__ \
// \/    \/\__,_|\__\___|_| |_|\___|_|  |___/
//

hazy.matcher = {
  // source of all fixture matchers
  pool: {},

  // registers a fixture pattern with a value into the matcher pool
  register: (path, value) => {
    hazy.matcher.pool[path] = value
  },

  // registers a fixture pattern with an advanced config into the matcher pool
  config: (config) => {
    const matcherPath    = config.path,
          matcherHandler = config.handle

    if (hazy.matcher.pool[matcherPath]) {
      delete hazy.matcher.pool[matcherPath]
    }

    hazy.matcher.pool[matcherPath] = {path: matcherPath, handle: matcherHandler}
  },

  // provides a map of all matched patterns in a fixture (pattern as key)
  matches: (fixture) => {
    let matches = {}

    if (hazy.config.matcher.use) {
      _.forEach(hazy.matcher.pool, (v, pattern) => {
        if (_.isObject(fixture)) {
          const jpMatches = jsonPath.query(fixture, pattern)

          if (!_.isEmpty(jpMatches)) {
            matches[pattern] = jpMatches
          }
        }
      })
    } else {
      // WARN - matching disabled
    }

    return matches
  },

  // determines if any matches in the pool apply to the fixture
  hasMatch: (fixture) => !_.isEmpty(
    hazy.matcher.matches(fixture)
  ),

  // search the fixture pool for fixtures matching a specific pattern (intentionally non-lazy- prone to recursion hell and there's also little benefit in evaluating random values)
  search: (pattern, process) => {
    const fixtures = _.values(hazy.fixture.pool)

    return _(fixtures)
      .map(fixture => {
        const jpMatches = jsonPath.query(fixture, pattern)

        if (!_.isEmpty(jpMatches)) {
          // process functional matches if desired
          if (_.isUndefined(process) ? hazy.config.matcher.use : process) {
            return hazy.matcher.process(pattern, fixture)
          }

          return fixture
        }
      })
      .reject(_.isUndefined)
      .value()
  },

  // executes a single pattern matcher handle on a fixture.
  // passive. does not consider non-matching patterns an error unless the matcher is corrupt
  process: (pattern, fixture) => {
    const matcher = hazy.matcher.pool[pattern]

    if (matcher) {
      if (_.isObject(matcher) && _.isFunction(matcher.handle)) {
        const matches = jsonPath.query(fixture, pattern)

        return matcher.handle(fixture, matches, pattern)
      } else {
        throw 'Match pattern does not apply to fixture or handle is not a function'
      }
    }

    return fixture
  },

  // executes handles for all pattern matches on a fixture
  processDeep: (fixture) => {
    const patternMatches = hazy.matcher.matches(fixture)
    let processedFixture = fixture

    _.forEach(patternMatches, (match, pattern) => {
      processedFixture = hazy.matcher.process(pattern, fixture) || processedFixture
    })

    return processedFixture
  }

}

//    __                 _
//   /__\ __ _ _ __   __| | ___  _ __ ___
//  / \/// _` | '_ \ / _` |/ _ \| '_ ` _ \
// / _  \ (_| | | | | (_| | (_) | | | | | |
// \/ \_/\__,_|_| |_|\__,_|\___/|_| |_| |_|
//

hazy.random = _.mapValues(hazy.meta.random.types, (value, key) => {
  let hazyRandObj = {}

  _.forEach(value, v => {
     hazyRandObj[v] = () => new Chance()[v]()
  })

  return hazyRandObj
})

//    ___       _ _     _
//   / __\_   _(_) | __| |
//  /__\// | | | | |/ _` |
// / \/  \ |_| | | | (_| |
// \_____/\__,_|_|_|\__,_|
//

// creates a clone of the current hazy object (shallow, new memory references)
hazy.fork = () => _.clone(hazy, false)

// convenience reference to lodash so that developers don't have to explicitly import the lib in their own code
hazy.util = _

// make the module accessible
module.exports = hazy
<|endoftext|>


<commit_before>'use strict';

var isString = require('lodash.isstring');
var isFunc = require('lodash.isfunction');
var isArray = require('lodash.isarray');

// Holds all the events and callbacks
// {
//    eventName: function() {}
// }
var eventContainer = {};

// Error handling
function handleRegisterType(type) {
    if (!isString(type) && !isArray(type)) {
        throw new TypeError('Event must be a string(event) or array of strings(events)');
    }
}

// If the event is a string put it in an array and return
function evtStrToArr(event) {
    if (!isString(event)) {
        return event;
    }

    event = [event];

    return event;
}

// Register event(s)
function register(event) {
    handleRegisterType(event);

    evtStrToArr(event).forEach(function(e) {
        if (eventContainer.hasOwnProperty(e)) {
            return false;
        }

        eventContainer[e] = [];

        return true;
    });
}

// Unregister event(s)
function unregister(event) {
    handleRegisterType(event);

    evtStrToArr(event).forEach(function(e) {
        if (!eventContainer.hasOwnProperty(e)) {
            return false;
        }

        delete eventContainer[e];

        return true;
    });
}

// Observe for events => fire a callback if we hit that event
function observer(event, callback) {
    if (!isString(event)) {
        throw new TypeError('Event must be a string');
    }

    if (!isFunc(callback)) {
        throw new TypeError('Callback must be a function');
    }

    if (!eventContainer.hasOwnProperty(event)) {
        return false;
    }

    eventContainer[event].push(callback);

    return true;
}

// Dispatch events with or without data
function dispatcher(event, data) {
    if (!isString(event)) {
        throw new TypeError('Event must be a string');
    }

    if (!eventContainer.hasOwnProperty(event)) {
        return false;
    }

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

    eventContainer[event].forEach(function(callback) {
        return data ? callback(data) : callback();
    });

    return true;
}

// Return every event available
function events() {
    return Object.keys(eventContainer);
}

module.exports = {
    register: register,
    unregister: unregister,
    dispatcher: dispatcher,
    observer: observer,
    events: events
};
<commit_msg>remove code I don't know why is added ¯\_(ツ)_/¯<commit_after>'use strict';

var isString = require('lodash.isstring');
var isFunc = require('lodash.isfunction');
var isArray = require('lodash.isarray');

// Holds all the events and callbacks
// {
//    eventName: function() {}
// }
var eventContainer = {};

// Error handling
function handleRegisterType(type) {
    if (!isString(type) && !isArray(type)) {
        throw new TypeError('Event must be a string(event) or array of strings(events)');
    }
}

// If the event is a string put it in an array and return
function evtStrToArr(event) {
    if (!isString(event)) {
        return event;
    }

    event = [event];

    return event;
}

// Register event(s)
function register(event) {
    handleRegisterType(event);

    evtStrToArr(event).forEach(function(e) {
        if (eventContainer.hasOwnProperty(e)) {
            return false;
        }

        eventContainer[e] = [];

        return true;
    });
}

// Unregister event(s)
function unregister(event) {
    handleRegisterType(event);

    evtStrToArr(event).forEach(function(e) {
        if (!eventContainer.hasOwnProperty(e)) {
            return false;
        }

        delete eventContainer[e];

        return true;
    });
}

// Observe for events => fire a callback if we hit that event
function observer(event, callback) {
    if (!isString(event)) {
        throw new TypeError('Event must be a string');
    }

    if (!isFunc(callback)) {
        throw new TypeError('Callback must be a function');
    }

    if (!eventContainer.hasOwnProperty(event)) {
        return false;
    }

    eventContainer[event].push(callback);

    return true;
}

// Dispatch events with or without data
function dispatcher(event, data) {
    if (!isString(event)) {
        throw new TypeError('Event must be a string');
    }

    if (!eventContainer.hasOwnProperty(event)) {
        return false;
    }

    eventContainer[event].forEach(function(callback) {
        return data ? callback(data) : callback();
    });

    return true;
}

// Return every event available
function events() {
    return Object.keys(eventContainer);
}

module.exports = {
    register: register,
    unregister: unregister,
    dispatcher: dispatcher,
    observer: observer,
    events: events
};
<|endoftext|>


<commit_before>"use strict";

var html = {};
var Handlebars = require("handlebars");
var _ = require("underscore");

html.templates = {};

html.compileTemplate = function(tplName) {
  var rawTemplate = $('script[name='+tplName+']').html();
  html.templates[tplName] = Handlebars.compile(rawTemplate);
};

html.renderTemplate = function(tplName, data) {
  return html.templates[tplName](data);
};

Handlebars.registerHelper('ifelse', function(cond, textIf, textElse) {
  textIf = Handlebars.Utils.escapeExpression(textIf);
  textElse  = Handlebars.Utils.escapeExpression(textElse);
  return new Handlebars.SafeString(cond ? textIf : textElse);
});

if (typeof window !== "undefined") {
  // A fake console to calm down some browsers.
  if (!window.console) {
    window.console = {
      log: function(msg) {
        // No-op
      }
    };
  }
}

// Render Underscore templates
html.tpl = function (tpl, ctx) {
  ctx = ctx || {};
  var source = $('script[name='+tpl+']').html();
  return _.template(source, ctx);
};

// Exports
// ====

module.exports = html;
<commit_msg>No handlebars.<commit_after>"use strict";

var html = {};
var _ = require("underscore");

html.templates = {};

// html.compileTemplate = function(tplName) {
//   var rawTemplate = $('script[name='+tplName+']').html();
//   html.templates[tplName] = Handlebars.compile(rawTemplate);
// };

html.renderTemplate = function(tplName, data) {
  return html.templates[tplName](data);
};

// Handlebars.registerHelper('ifelse', function(cond, textIf, textElse) {
//   textIf = Handlebars.Utils.escapeExpression(textIf);
//   textElse  = Handlebars.Utils.escapeExpression(textElse);
//   return new Handlebars.SafeString(cond ? textIf : textElse);
// });

if (typeof window !== "undefined") {
  // A fake console to calm down some browsers.
  if (!window.console) {
    window.console = {
      log: function(msg) {
        // No-op
      }
    };
  }
}

// Render Underscore templates
html.tpl = function (tpl, ctx) {
  ctx = ctx || {};
  var source = $('script[name='+tpl+']').html();
  return _.template(source, ctx);
};

// Exports
// ====

module.exports = html;
<|endoftext|>


<commit_before>export default {
  lng: 'en',
  nsSeparator: '::',
  keySeparator: '.|.',
  pluralSeparator: '._.',
  contextSeparator: '._.',
  resources: {
    en: {
      translation: {
        alertMessage: '{{label}}: {{message}}',
        complete: 'Submission Complete',
        error: 'Please fix the following errors before submitting.',
        submitError: 'Please check the form and correct all errors before submitting.',
        required: '{{field}} is required',
        unique: '{{field}} must be unique',
        array: '{{field}} must be an array',
        array_nonempty: '{{field}} must be a non-empty array', // eslint-disable-line camelcase
        nonarray: '{{field}} must not be an array',
        select: '{{field}} contains an invalid selection',
        pattern: '{{field}} does not match the pattern {{pattern}}',
        minLength: '{{field}} must have at least {{length}} characters.',
        maxLength: '{{field}} must have no more than {{length}} characters.',
        minWords: '{{field}} must have at least {{length}} words.',
        maxWords: '{{field}} must have no more than {{length}} words.',
        min: '{{field}} cannot be less than {{min}}.',
        max: '{{field}} cannot be greater than {{max}}.',
        maxDate: '{{field}} should not contain date after {{- maxDate}}',
        minDate: '{{field}} should not contain date before {{- minDate}}',
        maxYear: '{{field}} should not contain year greater than {{maxYear}}',
        minYear: '{{field}} should not contain year less than {{minYear}}',
        invalid_email: '{{field}} must be a valid email.', // eslint-disable-line camelcase
        invalid_url: '{{field}} must be a valid url.', // eslint-disable-line camelcase
        invalid_regex: '{{field}} does not match the pattern {{regex}}.', // eslint-disable-line camelcase
        invalid_date: '{{field}} is not a valid date.', // eslint-disable-line camelcase
        invalid_day: '{{field}} is not a valid day.', // eslint-disable-line camelcase
        mask: '{{field}} does not match the mask.',
        valueIsNotAvailable: '{{field}} conatains unavailable value',
        stripe: '{{stripe}}',
        month: 'Month',
        day: 'Day',
        year: 'Year',
        january: 'January',
        february: 'February',
        march: 'March',
        april: 'April',
        may: 'May',
        june: 'June',
        july: 'July',
        august: 'August',
        september: 'September',
        october: 'October',
        november: 'November',
        december: 'December',
        next: 'Next',
        previous: 'Previous',
        cancel: 'Cancel',
        submit: 'Submit Form',
        confirmCancel: 'Are you sure you want to cancel?',
        saveDraftInstanceError: 'Cannot save draft because there is no formio instance.',
        saveDraftAuthError: 'Cannot save draft unless a user is authenticated.',
        restoreDraftInstanceError: 'Cannot restore draft because there is no formio instance.',
        time: 'Invalid time'
      }
    }
  }
};
<commit_msg>Updated error message<commit_after>export default {
  lng: 'en',
  nsSeparator: '::',
  keySeparator: '.|.',
  pluralSeparator: '._.',
  contextSeparator: '._.',
  resources: {
    en: {
      translation: {
        alertMessage: '{{label}}: {{message}}',
        complete: 'Submission Complete',
        error: 'Please fix the following errors before submitting.',
        submitError: 'Please check the form and correct all errors before submitting.',
        required: '{{field}} is required',
        unique: '{{field}} must be unique',
        array: '{{field}} must be an array',
        array_nonempty: '{{field}} must be a non-empty array', // eslint-disable-line camelcase
        nonarray: '{{field}} must not be an array',
        select: '{{field}} contains an invalid selection',
        pattern: '{{field}} does not match the pattern {{pattern}}',
        minLength: '{{field}} must have at least {{length}} characters.',
        maxLength: '{{field}} must have no more than {{length}} characters.',
        minWords: '{{field}} must have at least {{length}} words.',
        maxWords: '{{field}} must have no more than {{length}} words.',
        min: '{{field}} cannot be less than {{min}}.',
        max: '{{field}} cannot be greater than {{max}}.',
        maxDate: '{{field}} should not contain date after {{- maxDate}}',
        minDate: '{{field}} should not contain date before {{- minDate}}',
        maxYear: '{{field}} should not contain year greater than {{maxYear}}',
        minYear: '{{field}} should not contain year less than {{minYear}}',
        invalid_email: '{{field}} must be a valid email.', // eslint-disable-line camelcase
        invalid_url: '{{field}} must be a valid url.', // eslint-disable-line camelcase
        invalid_regex: '{{field}} does not match the pattern {{regex}}.', // eslint-disable-line camelcase
        invalid_date: '{{field}} is not a valid date.', // eslint-disable-line camelcase
        invalid_day: '{{field}} is not a valid day.', // eslint-disable-line camelcase
        mask: '{{field}} does not match the mask.',
        valueIsNotAvailable: '{{ field }} is an invalid value.',
        stripe: '{{stripe}}',
        month: 'Month',
        day: 'Day',
        year: 'Year',
        january: 'January',
        february: 'February',
        march: 'March',
        april: 'April',
        may: 'May',
        june: 'June',
        july: 'July',
        august: 'August',
        september: 'September',
        october: 'October',
        november: 'November',
        december: 'December',
        next: 'Next',
        previous: 'Previous',
        cancel: 'Cancel',
        submit: 'Submit Form',
        confirmCancel: 'Are you sure you want to cancel?',
        saveDraftInstanceError: 'Cannot save draft because there is no formio instance.',
        saveDraftAuthError: 'Cannot save draft unless a user is authenticated.',
        restoreDraftInstanceError: 'Cannot restore draft because there is no formio instance.',
        time: 'Invalid time'
      }
    }
  }
};
<|endoftext|>


<commit_before>const Lang    = imports.lang;
const St      = imports.gi.St;
const Clutter = imports.gi.Clutter;
const ExUt    = imports.misc.extensionUtils;
const Me      = ExUt.getCurrentExtension();
const Utils   = Me.imports.utils;

const TeaPot = new Lang.Class({
	Name: 'TeaPot',
	Extends: St.DrawingArea,

	_init : function(size) {
		this.parent({ reactive : true });
        this.set_width(size);
        this.set_height(size);
		this.connect('repaint', Lang.bind(this, this._drawIcon));

		// some fallback color
		this._primaryColor = new Clutter.Color({
            red: 150,
            green: 150,
            blue: 150,
            alpha: 255
        });
	},
    setColor: function(col) {
		this._primaryColor = col;
		this.queue_repaint();
    },
	_drawIcon: function() {
	  	let cr    = this.get_context();
		let orWdt = 484;
		let orHgt = 295;
        let[width, height] = this.get_surface_size();

		Utils.setCairoColorFromClutter(cr, this._primaryColor);

		cr.save();

		// layout object in box
		if (orWdt/orHgt > width/height) {
			// take full width and center vertically
			cr.scale(width/orWdt, width/orWdt);
			cr.translate(0, (orWdt-orHgt)*0.5);
		} else {
			cr.scale(height/orHgt, height/orHgt)
			cr.translate(-(orWdt-orHgt)*0.5, 0);;
		}

		// draw TeaPot
		// cairo commands generated from svg2cairo
		// https://github.com/akrinke/svg2cairo

		cr.moveTo(127.894531, 276.472656);
		cr.curveTo(98.457031, 244.316406, 76.527344, 238.09375, 47.953125, 210.996094);
		cr.curveTo(17.957031, 186.902344, -7.5625, 148.257812, 2.066406, 108.261719);
		cr.curveTo(6.914062, 83.1875, 33.097656, 66.261719, 57.921875, 71.910156);
		cr.curveTo(75.457031, 74.132812, 91.273438, 82.546875, 106.296875, 91.351562);
		cr.curveTo(115.582031, 75.792969, 143.570312, 72.222656, 134.984375, 50.113281);
		cr.curveTo(148.652344, 38.449219, 169.386719, 38.300781, 186.574219, 34.550781);
		cr.curveTo(194.753906, 31.46875, 224.667969, 35.746094, 204.664062, 27.492188);
		cr.curveTo(191.921875, 8.488281, 224.023438, -2.769531, 239.1875, 0.589844);
		cr.curveTo(266.851562, -1.550781, 262.417969, 31.988281, 246.710938, 32.113281);
		cr.curveTo(277.785156, 34.632812, 309.761719, 36.359375, 339.148438, 47.523438);
		cr.curveTo(349.664062, 56.277344, 334.71875, 72.871094, 353.0625, 77.5625);
		cr.curveTo(365.789062, 87.367188, 373.671875, 119.875, 391.816406, 97.292969);
		cr.curveTo(408.726562, 84.214844, 418.597656, 56.902344, 444.113281, 60.386719);
		cr.curveTo(455.804688, 60.738281, 498.675781, 59.714844, 478.949219, 78.144531);
		cr.curveTo(459.007812, 90.46875, 438.289062, 106.699219, 434.382812, 131.382812);
		cr.curveTo(424.910156, 164.207031, 403.375, 177.308594, 377.503906, 202.261719);
		cr.curveTo(356.9375, 218.46875, 366.351562, 240.726562, 316.707031, 285.832031);
		cr.curveTo(289.941406, 297.757812, 175.589844, 302.082031, 127.894531, 276.472656);
		cr.closePath();
		cr.moveTo(83.28125, 184.4375);
		cr.curveTo(78.351562, 164.75, 89.941406, 143.515625, 85.308594, 124.882812);
		cr.curveTo(73.085938, 112.210938, 40.816406, 104.996094, 44.332031, 130.574219);
		cr.curveTo(48.808594, 142.773438, 71.621094, 185.558594, 83.28125, 184.4375);
		cr.closePath();
		cr.moveTo(83.28125, 184.4375);
		cr.setTolerance(0.1);
		cr.fillPreserve();

		// end of image
		cr.restore();
	}

});

<commit_msg>add comments<commit_after>/*********************************************************************
 * A small custom icon class, which draws a two bit icon centered and
 * maximized, preserving the aspect ratio.
 *
 * This class was introduced to solve the following problems:
 *  a) draw the icon with the current theme color
 *  b) to work-around the strange streched icon I get in gnome-3.14
 *
 * If there is a better way for a) using my previous svg icon file,
 * please let me know ;)
 ********************************************************************/

const Lang    = imports.lang;
const St      = imports.gi.St;
const Clutter = imports.gi.Clutter;
const ExUt    = imports.misc.extensionUtils;
const Me      = ExUt.getCurrentExtension();
const Utils   = Me.imports.utils;

const TeaPot = new Lang.Class({
	Name: 'TeaPot',
	Extends: St.DrawingArea,

	_init : function(size) {
		this.parent({ reactive : true });
        this.set_width(size);
        this.set_height(size);
		this.connect('repaint', Lang.bind(this, this._drawIcon));

		// some fallback color
		this._primaryColor = new Clutter.Color({
            red: 150,
            green: 150,
            blue: 150,
            alpha: 255
        });
	},
    setColor: function(col) {
		this._primaryColor = col;
		this.queue_repaint();
    },
	_drawIcon: function() {
	  	let cr    = this.get_context();
		let orWdt = 484; // from the svg file
		let orHgt = 295;
        let[width, height] = this.get_surface_size();

		Utils.setCairoColorFromClutter(cr, this._primaryColor);

		cr.save();

		// layout object in box
		if (orWdt/orHgt > width/height) {
			// take full width and center vertically
			cr.scale(width/orWdt, width/orWdt);
			cr.translate(0, (orWdt-orHgt)*0.5);
		} else {
			cr.scale(height/orHgt, height/orHgt)
			cr.translate(-(orWdt-orHgt)*0.5, 0);;
		}

		// draw TeaPot
		// cairo commands generated from svg2cairo
		// https://github.com/akrinke/svg2cairo

		cr.moveTo(127.894531, 276.472656);
		cr.curveTo(98.457031, 244.316406, 76.527344, 238.09375, 47.953125, 210.996094);
		cr.curveTo(17.957031, 186.902344, -7.5625, 148.257812, 2.066406, 108.261719);
		cr.curveTo(6.914062, 83.1875, 33.097656, 66.261719, 57.921875, 71.910156);
		cr.curveTo(75.457031, 74.132812, 91.273438, 82.546875, 106.296875, 91.351562);
		cr.curveTo(115.582031, 75.792969, 143.570312, 72.222656, 134.984375, 50.113281);
		cr.curveTo(148.652344, 38.449219, 169.386719, 38.300781, 186.574219, 34.550781);
		cr.curveTo(194.753906, 31.46875, 224.667969, 35.746094, 204.664062, 27.492188);
		cr.curveTo(191.921875, 8.488281, 224.023438, -2.769531, 239.1875, 0.589844);
		cr.curveTo(266.851562, -1.550781, 262.417969, 31.988281, 246.710938, 32.113281);
		cr.curveTo(277.785156, 34.632812, 309.761719, 36.359375, 339.148438, 47.523438);
		cr.curveTo(349.664062, 56.277344, 334.71875, 72.871094, 353.0625, 77.5625);
		cr.curveTo(365.789062, 87.367188, 373.671875, 119.875, 391.816406, 97.292969);
		cr.curveTo(408.726562, 84.214844, 418.597656, 56.902344, 444.113281, 60.386719);
		cr.curveTo(455.804688, 60.738281, 498.675781, 59.714844, 478.949219, 78.144531);
		cr.curveTo(459.007812, 90.46875, 438.289062, 106.699219, 434.382812, 131.382812);
		cr.curveTo(424.910156, 164.207031, 403.375, 177.308594, 377.503906, 202.261719);
		cr.curveTo(356.9375, 218.46875, 366.351562, 240.726562, 316.707031, 285.832031);
		cr.curveTo(289.941406, 297.757812, 175.589844, 302.082031, 127.894531, 276.472656);
		cr.closePath();
		cr.moveTo(83.28125, 184.4375);
		cr.curveTo(78.351562, 164.75, 89.941406, 143.515625, 85.308594, 124.882812);
		cr.curveTo(73.085938, 112.210938, 40.816406, 104.996094, 44.332031, 130.574219);
		cr.curveTo(48.808594, 142.773438, 71.621094, 185.558594, 83.28125, 184.4375);
		cr.closePath();
		cr.moveTo(83.28125, 184.4375);
		cr.setTolerance(0.1);
		cr.fillPreserve();

		// end of image
		cr.restore();
	}

});

<|endoftext|>


<commit_before>// Copyright (c) 2011-2012 UX Productivity Pty Ltd. All rights reserved.

function prettyPrintDocument()
{
    var clone = document.documentElement.cloneNode(true);
    removeRedundantWhitespace(clone,"");
    addIndentation(clone,"");
    return clone.outerHTML;

    function isWhitespaceChar(c)
    {
        return ((c == " ") || (c == "\t") || (c == "\r") || (c == "\n"));
    }

    // Note: This could potentially remove some whitespace that is important, e.g.
    // in the case of <b>one </b>two... it should only be used for debugging purposes
    function removeRedundantWhitespace(node,indent)
    {
        if (node.nodeType == Node.ELEMENT_NODE) {
            var next;
            for (var child = node.firstChild; child != null; child = next) {
                next = child.nextSibling;
                if (isWhitespaceTextNode(child)) {
                    node.removeChild(child);
                }
                else {
                    removeRedundantWhitespace(child,indent+"    ");
                }
            }
        }
        else if (node.nodeType == Node.TEXT_NODE) {
            var str = node.nodeValue;
            var start = 0;
            var end = str.length;
            while ((start < end) && isWhitespaceChar(str.charAt(start)))
                start++;
            while ((end > start) && isWhitespaceChar(str.charAt(end-1)))
                end--;
            node.nodeValue = str.slice(start,end);
        }
    }

    function addIndentation(node,indent)
    {
        if (node.nodeType == Node.ELEMENT_NODE) {
            var next;
            for (var child = node.firstChild; child != null; child = next) {
                next = child.nextSibling;
                var text = document.createTextNode("\n"+indent+"    ");
                node.insertBefore(text,child);
                addIndentation(child,indent+"    ");
            }
            var text = document.createTextNode("\n"+indent);
            node.appendChild(text);
        }
    }
}

function getDOMTree()
{
    var root = convertToObjects(document.documentElement);
    return JSON.stringify(root);

    function convertToObjects(node)
    {
        var obj = new Object();
        obj.nodeType = node.nodeType;
        if (node.nodeType == Node.ELEMENT_NODE) {
            obj.nodeName = node.nodeName;
            obj.attributes = new Object();
            for (var i = 0; i < node.attributes.length; i++) {
                var attr = node.attributes[i];
                obj.attributes[attr.nodeName] = attr.nodeValue;
            }
            obj.childNodes = new Array();
            for (var child = node.firstChild; child != null; child = child.nextSibling)
                obj.childNodes.push(convertToObjects(child));
        }
        else if (node.nodeType == Node.TEXT_NODE) {
            obj.nodeValue = node.nodeValue;
        }
        else {
            throw new Error("Unexpected node type: "+node.nodeType);
        }
        return obj;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//                                          General                                               //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////

function getStyles()
{
    var list = new Array();
    for (var i = 0; i < document.styleSheets.length; i++) {
        var sheet = document.styleSheets[i];
        var str = "";
        for (name in sheet)
            str += name+"\n";
        for (var j = 0; j < sheet.cssRules.length; j++) {
            var rule = sheet.cssRules[j];
            if (rule.type == CSSRule.STYLE_RULE) {
                var properties = new Object();
                for (k = 0; k < rule.style.length; k++)
                    properties[rule.style[k]] = rule.style.getPropertyValue(rule.style[k]);

                list.push({"selector": rule.selectorText,
                           "properties": properties });
            }
        }
    }
    editor.setStyles(list);
}

function jumpToSection(sectionId)
{
    var section = document.getElementById(sectionId);
    var location = webkitConvertPointFromNodeToPage(section,
                                                    new WebKitPoint(0,0));
    window.scrollTo(0,location.y);
}

function getHTML()
{
    try {
        var serializer = new XMLSerializer();
        var xml = serializer.serializeToString(document);
        editor.getHTMLResponse(xml);
    }
    catch (e) {
        editor.getHTMLError(e.toString());
    }
}

function keydown(e)
{
    if (e.keyCode == '\r'.charCodeAt(0)) {
        e.preventDefault();
        enterPressed();
    }
}

// Remove the temporary <script> element that was added to the document to execute this file
// so it's not saved with the document
var initscript = document.getElementById("initscript");
if (initscript != null) {
    initscript.parentNode.removeChild(initscript);
}

var jsInitOk = false;
try {
    DOM.assignNodeIds(document);
//    document.body.contentEditable = true;
//    document.body.style.padding = "15%";
//    document.body.style.padding = "5%";
    document.body.style.textAlign = "justify";
    window.onkeydown = keydown;

    setupMutation();
    getOutline();
    getStyles();
    structure.examineDocument();
    jsInitOk = true;
}
catch (e) {
    editor.jsInterfaceInitError(e.stack);
}

if (jsInitOk)
    editor.jsInterfaceInitFinished();
<commit_msg>Moved the javascript initialisation code into a function, init(). This means it is no longer necessary to load init.js last.<commit_after>// Copyright (c) 2011-2012 UX Productivity Pty Ltd. All rights reserved.

function prettyPrintDocument()
{
    var clone = document.documentElement.cloneNode(true);
    removeRedundantWhitespace(clone,"");
    addIndentation(clone,"");
    return clone.outerHTML;

    function isWhitespaceChar(c)
    {
        return ((c == " ") || (c == "\t") || (c == "\r") || (c == "\n"));
    }

    // Note: This could potentially remove some whitespace that is important, e.g.
    // in the case of <b>one </b>two... it should only be used for debugging purposes
    function removeRedundantWhitespace(node,indent)
    {
        if (node.nodeType == Node.ELEMENT_NODE) {
            var next;
            for (var child = node.firstChild; child != null; child = next) {
                next = child.nextSibling;
                if (isWhitespaceTextNode(child)) {
                    node.removeChild(child);
                }
                else {
                    removeRedundantWhitespace(child,indent+"    ");
                }
            }
        }
        else if (node.nodeType == Node.TEXT_NODE) {
            var str = node.nodeValue;
            var start = 0;
            var end = str.length;
            while ((start < end) && isWhitespaceChar(str.charAt(start)))
                start++;
            while ((end > start) && isWhitespaceChar(str.charAt(end-1)))
                end--;
            node.nodeValue = str.slice(start,end);
        }
    }

    function addIndentation(node,indent)
    {
        if (node.nodeType == Node.ELEMENT_NODE) {
            var next;
            for (var child = node.firstChild; child != null; child = next) {
                next = child.nextSibling;
                var text = document.createTextNode("\n"+indent+"    ");
                node.insertBefore(text,child);
                addIndentation(child,indent+"    ");
            }
            var text = document.createTextNode("\n"+indent);
            node.appendChild(text);
        }
    }
}

function getDOMTree()
{
    var root = convertToObjects(document.documentElement);
    return JSON.stringify(root);

    function convertToObjects(node)
    {
        var obj = new Object();
        obj.nodeType = node.nodeType;
        if (node.nodeType == Node.ELEMENT_NODE) {
            obj.nodeName = node.nodeName;
            obj.attributes = new Object();
            for (var i = 0; i < node.attributes.length; i++) {
                var attr = node.attributes[i];
                obj.attributes[attr.nodeName] = attr.nodeValue;
            }
            obj.childNodes = new Array();
            for (var child = node.firstChild; child != null; child = child.nextSibling)
                obj.childNodes.push(convertToObjects(child));
        }
        else if (node.nodeType == Node.TEXT_NODE) {
            obj.nodeValue = node.nodeValue;
        }
        else {
            throw new Error("Unexpected node type: "+node.nodeType);
        }
        return obj;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//                                          General                                               //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////

function getStyles()
{
    var list = new Array();
    for (var i = 0; i < document.styleSheets.length; i++) {
        var sheet = document.styleSheets[i];
        var str = "";
        for (name in sheet)
            str += name+"\n";
        for (var j = 0; j < sheet.cssRules.length; j++) {
            var rule = sheet.cssRules[j];
            if (rule.type == CSSRule.STYLE_RULE) {
                var properties = new Object();
                for (k = 0; k < rule.style.length; k++)
                    properties[rule.style[k]] = rule.style.getPropertyValue(rule.style[k]);

                list.push({"selector": rule.selectorText,
                           "properties": properties });
            }
        }
    }
    editor.setStyles(list);
}

function jumpToSection(sectionId)
{
    var section = document.getElementById(sectionId);
    var location = webkitConvertPointFromNodeToPage(section,
                                                    new WebKitPoint(0,0));
    window.scrollTo(0,location.y);
}

function getHTML()
{
    try {
        var serializer = new XMLSerializer();
        var xml = serializer.serializeToString(document);
        editor.getHTMLResponse(xml);
    }
    catch (e) {
        editor.getHTMLError(e.toString());
    }
}

function keydown(e)
{
    if (e.keyCode == '\r'.charCodeAt(0)) {
        e.preventDefault();
        enterPressed();
    }
}

function init()
{
    var jsInitOk = false;
    try {
        DOM.assignNodeIds(document);
        document.body.style.textAlign = "justify";
        window.onkeydown = keydown;

        setupMutation();
        getOutline();
        getStyles();
        structure.examineDocument();
        jsInitOk = true;
    }
    catch (e) {
        editor.jsInterfaceInitError(e.stack);
    }

    if (jsInitOk)
        editor.jsInterfaceInitFinished();
}
<|endoftext|>