(function() {
  if (this.PokeBattle == null) {
    this.PokeBattle = {};
  }

  PokeBattle.battles = null;

  PokeBattle.events = {};

  _.extend(PokeBattle.events, Backbone.Events);

}).call(this);

(function() {
  PokeBattle.events.once("ready", function() {
    var $loading;
    $loading = $(".loading-container");
    return $loading.fadeOut(function() {
      return $loading.remove();
    });
  });

}).call(this);

(function() {
  Backbone.Associations.EVENTS_NC = true;

}).call(this);

(function() {
  var __slice = [].slice;

  this.makeBiasedRng = function(battle) {
    var biasedRNGFuncs, funcName, _fn, _i, _len, _ref;
    biasedRNGFuncs = {};
    _ref = ['next', 'randInt'];
    _fn = (function(_this) {
      return function(funcName) {
        var oldFunc;
        oldFunc = battle.rng[funcName].bind(battle.rng);
        return battle.rng[funcName] = function() {
          var args, func, id;
          args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
          id = args[args.length - 1];
          func = biasedRNGFuncs[funcName];
          return (id in func ? func[id] : oldFunc.apply(null, args));
        };
      };
    })(this);
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      funcName = _ref[_i];
      _fn(funcName);
    }
    return battle.rng.bias = function(funcName, id, returns) {
      biasedRNGFuncs[funcName] || (biasedRNGFuncs[funcName] = {});
      return biasedRNGFuncs[funcName][id] = returns;
    };
  };

}).call(this);

(function() {
  var CannedText, allTexts, cannedMap, cannedMapReverse, cannedTextName, cannedTextNames, cannedTexts, counter, generation, generationName, i, language, _i, _j, _len, _len1, _ref,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  CannedText = {
    bw: {
      en: {
        MOVE_MISS: "$p avoided the attack!",
        MOVE_FAIL: "But it failed!",
        SUPER_EFFECTIVE: "It's super effective!",
        NOT_VERY_EFFECTIVE: "It's not very effective...",
        CRITICAL_HIT: "A critical hit!",
        GOT_HIT: "$p took $1% damage!",
        DRAIN: "$p had its energy drained!",
        ABSORB: "$p absorbed some HP!",
        NO_TARGET: "But there was no target...",
        RECOIL: "$p was hit by recoil!",
        IMMUNITY: "But it doesn't affect $p...",
        FLINCH: "$p flinched!",
        IS_CONFUSED: "$p is confused!",
        CONFUSION_START: "$p became confused!",
        CONFUSION_END: "$p snapped out of confusion!",
        CONFUSION_HURT_SELF: "$p hurt itself in confusion!",
        FATIGUE: "$p became confused due to fatigue!",
        NO_MOVES_LEFT: "$p has no moves left!",
        NO_PP_LEFT: "But there was no PP left for the move!",
        SUN_START: "The sunlight turned harsh!",
        RAIN_START: "It started to rain!",
        SAND_START: "A sandstorm kicked up!",
        HAIL_START: "It started to hail!",
        SUN_END: "The sunlight faded.",
        RAIN_END: "The rain stopped.",
        SAND_END: "The sandstorm subsided.",
        HAIL_END: "The hail stopped.",
        SAND_CONTINUE: "The sandstorm rages.",
        HAIL_CONTINUE: "The hail crashes down.",
        SAND_HURT: "$p is buffeted by the sandstorm!",
        HAIL_HURT: "$p is buffeted by the hail!",
        DISABLE_START: "$p's $m was disabled!",
        DISABLE_CONTINUE: "$p's $m is disabled!",
        DISABLE_END: "$p is no longer disabled!",
        YAWN_BEGIN: "$p grew drowsy!",
        TAUNT_START: "$p fell for the taunt!",
        TAUNT_PREVENT: "$p can't use $m after the taunt!",
        TAUNT_END: "$p's taunt wore off!",
        WISH_END: "$1's wish came true!",
        PERISH_SONG_START: "All Pokemon hearing the song will faint in three turns!",
        PERISH_SONG_CONTINUE: "$p's perish count fell to $1!",
        TAILWIND_END: "The tailwind petered out!",
        ENCORE_END: "$p's Encore ended!",
        TORMENT_START: "$p was subjected to Torment!",
        SPIKES_START: "Spikes were scattered all around $ts's feet!",
        SPIKES_HURT: "$p is hurt by the spikes!",
        SPIKES_END: "The spikes disappeared from around $ts's feet!",
        STEALTH_ROCK_START: "Pointed stones float in the air around $ts!",
        STEALTH_ROCK_HURT: "Pointed stones dug into $p!",
        STEALTH_ROCK_END: "The pointed stones disappeared from around $ts!",
        TOXIC_SPIKES_START: "Poison spikes were scattered all around $ts's feet!",
        TOXIC_SPIKES_END: "The poison spikes disappeared from around $ts's feet!",
        TRAP_HURT: "$p is hurt by $m!",
        LEECH_SEED_START: "$p was seeded!",
        LEECH_SEED_HURT: "$p's health is sapped by Leech Seed!",
        PROTECT_CONTINUE: "$p protected itself!",
        DESTINY_BOND_START: "$p is trying to take its foe down with it!",
        DESTINY_BOND_CONTINUE: "$p took its attacker down with it!",
        SUBSTITUTE_START: "$p put in a substitute!",
        SUBSTITUTE_EXISTS: "$p already has a substitute!",
        SUBSTITUTE_WEAK: "It was too weak to make a substitute!",
        SUBSTITUTE_END: "$p's substitute faded!",
        SUBSTITUTE_HURT: "The substitute took damage for $p!",
        BOUNCE_MOVE: "$p bounced the $m back!",
        TRICK_ROOM_START: "$p twisted the dimensions!",
        TRICK_ROOM_END: "The twisted dimensions returned to normal!",
        PARALYZE_START: '$p was paralyzed!',
        FREEZE_START: '$p was frozen!',
        POISON_START: '$p was poisoned!',
        TOXIC_START: '$p was badly poisoned!',
        SLEEP_START: '$p fell asleep!',
        BURN_START: '$p was burned!',
        PARALYZE_CONTINUE: '$p is fully paralyzed!',
        FREEZE_CONTINUE: "$p is frozen solid!",
        POISON_CONTINUE: "$p was hurt by poison!",
        SLEEP_CONTINUE: "$p is fast asleep.",
        BURN_CONTINUE: "$p was hurt by its burn!",
        RECOVER_HP: "$p's HP was restored.",
        TRICK_START: "$p switched items with its target!",
        TRICK_END: "$p obtained one $i!",
        THIEF_START: "$p stole $p's $i!",
        RESET_STATS: "$p's stat changes were removed!",
        RESET_ALL_STATS: "All stat changes were eliminated!",
        JUMP_KICK_MISS: "$p kept going and crashed!",
        FREE_FROM: "$p was freed from $1!",
        TRANSFORM: '$p transformed!',
        TRANSFORM_INTO: '$p transformed into $p!',
        TRANSFORM_TYPE: "$p transformed into the $y type!",
        ACQUIRE_ABILITY: "$p acquired $a!",
        REFLECT_START: "Reflect raised $ts's defense!",
        LIGHT_SCREEN_START: "Light Screen raised $ts's special defense!",
        REFLECT_END: "$ts's Reflect wore off!",
        LIGHT_SCREEN_END: "$ts's Light Screen wore off!",
        STICKY_WEB_START: "A sticky web has been laid out beneath $ts's feet!",
        STICKY_WEB_CONTINUE: "$p was caught in a sticky web!",
        STICKY_WEB_END: "The sticky web has disappeared from beneath $ts's feet!",
        RATING_UPDATE: "$t's rating: $1 -> $2",
        KNOCK_OFF: "$p knocked off $p's $i!",
        PAIN_SPLIT: "The battlers shared their pain!",
        PAY_DAY: "Coins were scattered everywhere!",
        PSYCH_UP: "$p copied $p's stat changes!",
        MENTAL_HERB: "$p used its Mental Herb to come back to its senses!",
        WHITE_HERB: "$p restored its status using its White Herb!",
        RED_CARD: "$p held up its Red Card against $p!",
        EJECT_BUTTON: "$p is switched out with the Eject Button!",
        HANG_ON: "$p hung on using its $i!",
        MOVE_FIRST: "$p's $i let it move first!",
        SAFEGUARD_START: "$t's team became cloaked in a mystical veil!",
        SAFEGUARD_END: "$t's Safeguard wore off!",
        ITEM_RESTORE: "$p restored a little HP using its $i!",
        ITEM_WEAKEN: "The $i weakened the damage to $p!",
        POKEMON_HURT_BY_ITEM: "$p is hurt by $p's $i!",
        ITEM_SELF_HURT: "$p is hurt by its $i!",
        POKEMON_HURT: "$p is hurt!",
        BERRY_RESTORE: "$p restored its health using its $i!",
        BERRY_RAISE_STAT: "The $i raised $p's $1!",
        GEM_BOOST: "The $i strengthened $m's power!",
        ENDURE: "$p endured the hit!",
        ANCHOR: "$p anchors itself!",
        AVOID_ALLIES: "$p avoids attacks by its ally Pokemon!",
        TRACE: "It traced the foe's $a!",
        TRUANT: "$p is loafing around!",
        WEATHER_DISABLED: "The effects of weather disappeared.",
        MOLD_BREAKER: "$p breaks the mold!",
        TERAVOLT: "$p is radiating a bursting aura!",
        TURBOBLAZE: "$p is radiating a blazing aura!",
        ANTICIPATION: "$p shuddered!",
        BAD_DREAMS: "$p is tormented!",
        COLOR_CHANGE: "$p's Color Change made it the $1 type!",
        FLASH_FIRE: "The power of $p's Fire-type moves rose!",
        FOREWARN: "It was alerted to $p's $m!",
        FRISK: "$p frisked its target and found one $i!",
        HARVEST: "$p harvested one $i!",
        PRESSURE: "$p is exerting its pressure!",
        MUMMY: "$p's ability became Mummy!",
        PICKPOCKET: "$p stole $p's $i!",
        SLOW_START_START: "$p can't get it going!",
        SLOW_START_END: "$p finally got its act together!",
        WITHDREW: "$t withdrew $p!",
        SENT_OUT: "$t sent out $p!",
        SWAP_ABILITY: "$p swapped Abilities with its target!",
        TELEKINESIS_START: "$p was hurled into the air!",
        TELEKINESIS_END: "$p was freed from the telekinesis!",
        HEAL_BLOCK_START: "$p was prevented from healing!",
        HEAL_BLOCK_END: "$p's Heal Block wore off!",
        HEAL_BLOCK_PREVENT: "$p can't use $m because of Heal Block!",
        HEAL_BLOCK_TRY_HEAL: "$p was prevented from healing due to Heal Block!",
        HEAL_BLOCK_FAIL: "But it failed to affect $p!",
        FOUND_ITEM: "$p found one $i!",
        MOON_START: "$p's Noctem darkened the sky!",
        MOON_END: "The sky brightened again.",
        MOON_CONTINUE: "The sky is dark.",
        LIVEWIRE_START: "A wire was set at the feet of the foe",
        LIVEWIRE_END: "$p absorbed the Livewire!",
        LIVEWIRE_HURT: "$p was shocked by the Livewire!",
        LIVEWIRE_MISS: "$p avoided the Livewire!",
        FIRE_ROCK_START: "Molten rocks float in the air around $ts!",
        FIRE_ROCK_HURT: "$p is hurt by molten rocks!",
        FIRE_ROCK_END: "The molten rocks disappeared from around $ts!",
        ILLUSION_BROKE: "The foes $p broke it's illusion!"
      }
    }
  };

  cannedMap = {};

  cannedMapReverse = {};

  allTexts = [];

  counter = 0;

  cannedTextNames = [];

  for (generationName in CannedText) {
    generation = CannedText[generationName];
    for (language in generation) {
      cannedTexts = generation[language];
      _ref = Object.keys(cannedTexts);
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        cannedTextName = _ref[_i];
        if (__indexOf.call(cannedTextNames, cannedTextName) < 0) {
          cannedTextNames.push(cannedTextName);
        }
      }
    }
  }

  cannedTextNames.sort();

  for (i = _j = 0, _len1 = cannedTextNames.length; _j < _len1; i = ++_j) {
    cannedTextName = cannedTextNames[i];
    counter = i + 1;
    cannedMap[cannedTextName] = counter;
    cannedMapReverse[counter] = cannedTextName;
  }

  this.CannedText = cannedMap;

  this.CannedMap = CannedText;

  this.CannedMapReverse = cannedMapReverse;

}).call(this);

(function() {
  var self, _base;

  self = (typeof window !== "undefined" && window !== null ? (_base = window.PokeBattle).conditions != null ? _base.conditions : _base.conditions = {} : this);

  this.Conditions = {
    TEAM_PREVIEW: 1,
    RATED_BATTLE: 2,
    PBV_1000: 3,
    TIMED_BATTLE: 4,
    SLEEP_CLAUSE: 5,
    SPECIES_CLAUSE: 6,
    EVASION_CLAUSE: 7,
    OHKO_CLAUSE: 8,
    UNRELEASED_BAN: 9,
    PRANKSTER_SWAGGER_CLAUSE: 10,
    PBV_500: 11,
    VISIBLE_TEAM: 12,
    TIER_LC: 13,
    TIER_PU: 14,
    TIER_NU: 15,
    TIER_RU: 16,
    TIER_UU: 17,
    TIER_OU: 18,
    TIER_Uber: 19
  };

  this.SelectableConditions = [this.Conditions.VISIBLE_TEAM, this.Conditions.TIMED_BATTLE, this.Conditions.SLEEP_CLAUSE, this.Conditions.EVASION_CLAUSE, this.Conditions.SPECIES_CLAUSE, this.Conditions.PRANKSTER_SWAGGER_CLAUSE, this.Conditions.OHKO_CLAUSE, this.Conditions.UNRELEASED_BAN];

  this.HumanizedConditions = {
    en: {
      VISIBLE_TEAM: "Visible Teams",
      TEAM_PREVIEW: "Team Preview",
      SLEEP_CLAUSE: "Sleep Clause",
      RATED_BATTLE: "Rated Battle",
      TIMED_BATTLE: "Timed Battle",
      SPECIES_CLAUSE: "Species Clause",
      EVASION_CLAUSE: "Evasion Clause",
      OHKO_CLAUSE: "One-Hit KO Clause",
      UNRELEASED_BAN: "Unreleased Ban",
      PRANKSTER_SWAGGER_CLAUSE: "Prankster + Swagger Clause"
    }
  };

  self.PresetFormats = {
    insur1000: {
      name: 'insur1000',
      humanName: 'Insurgence 1000',
      generation: 'in',
      conditions: [this.Conditions.PBV_1000, this.Conditions.TEAM_PREVIEW],
      playable: true,
      priority: 5,
      tierBased: false
    },
    xy1000: {
      name: 'xy1000',
      humanName: '1,000 PBV XY',
      generation: 'xy',
      conditions: [this.Conditions.PBV_1000, this.Conditions.TEAM_PREVIEW],
      playable: true,
      priority: 10,
      tierBased: false
    },
    xy500: {
      name: 'xy500',
      humanName: '500 PBV XY',
      generation: 'xy',
      conditions: [this.Conditions.PBV_500, this.Conditions.TEAM_PREVIEW],
      playable: true,
      priority: 10,
      tierBased: false
    }
  };

  this.GenerationCondition = {
    'in': {
      conditionname: 'insur',
      humanName: 'Insurgence'
    }
  };

  self.Formats_ = {};

  self.Formats = function() {
    if (Object.keys(this.Formats_).length === 0) {
      this.setFormats();
      return this.Formats_;
    } else {
      return this.Formats_;
    }
  };

  self.setFormats = function() {
    var Tiers, conditions, finalobj, format, formatname, gen, humanname, key, newformats, playablegens, priority, sortedformatsarr, tier, tierData, tierbased, _, _conditions, _i, _j, _len, _len1;
    playablegens = ['in'];
    newformats = this.PresetFormats;
    if (typeof window !== "undefined" && window !== null) {
      Tiers = window.PokeBattle.Tier.Tiers;
      conditions = Conditions;
      _ = window._;
    } else {
      Tiers = require('./tier').Tiers;
      conditions = this.Conditions;
      _ = require('underscore')._;
    }
    for (key in conditions) {
      if ((key.search(/TIER_/)) === 0) {
        tier = key.replace(/TIER_/, "");
        tierData = Tiers[tier];
        if (tierData.playable) {
          for (_i = 0, _len = playablegens.length; _i < _len; _i++) {
            gen = playablegens[_i];
            tierbased = true;
            if (typeof window !== "undefined" && window !== null) {
              formatname = GenerationCondition[gen].conditionname + tier;
              _conditions = [Conditions[key], Conditions.TEAM_PREVIEW];
              priority = tierData.priority;
              humanname = "" + GenerationCondition[gen].humanName + " " + tierData.humanName;
            } else {
              formatname = this.GenerationCondition[gen].conditionname + tier;
              _conditions = [this.Conditions[key], this.Conditions.TEAM_PREVIEW];
              priority = tierData.priority;
              humanname = "" + this.GenerationCondition[gen].humanName + " " + tierData.humanName;
            }
            newformats[formatname] = {
              name: formatname,
              humanName: humanname,
              generation: gen,
              conditions: _conditions,
              priority: priority,
              tierBased: tierbased
            };
          }
        }
      }
    }
    sortedformatsarr = _.sortBy(newformats, 'priority');
    finalobj = {};
    for (_j = 0, _len1 = sortedformatsarr.length; _j < _len1; _j++) {
      format = sortedformatsarr[_j];
      finalobj[format.name] = format;
    }
    return this.Formats_ = finalobj;
  };

  this.DEFAULT_FORMAT = 'insurOU';

}).call(this);

(function() {
  var error, errors, i, self, _i, _len, _ref;

  self = (typeof module !== "undefined" && module !== null ? module.exports : void 0) || (window.PokeBattle.errors = {});

  errors = "FIND_BATTLE\nBATTLE_DNE\nINVALID_SESSION\nBANNED\nCOMMAND_ERROR\nPRIVATE_MESSAGE\nINVALID_ALT_NAME";

  _ref = errors.trim().split(/\s+/);
  for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
    error = _ref[i];
    self[error] = i + 1;
  }

}).call(this);

(function() {
  var self;

  self = (typeof module !== "undefined" && module !== null ? module.exports : window.HiddenPower != null ? window.HiddenPower : window.HiddenPower = {});

  if (self.BW == null) {
    self.BW = {};
  }

  self.BW.types = ['Fighting', 'Flying', 'Poison', 'Ground', 'Rock', 'Bug', 'Ghost', 'Steel', 'Fire', 'Water', 'Grass', 'Electric', 'Psychic', 'Ice', 'Dragon', 'Dark'];

  self.BW.basePower = function(ivs) {
    var base;
    base = 0;
    if (ivs['hp'] % 4 > 1) {
      base += 1;
    }
    if (ivs['attack'] % 4 > 1) {
      base += 2;
    }
    if (ivs['defense'] % 4 > 1) {
      base += 4;
    }
    if (ivs['speed'] % 4 > 1) {
      base += 8;
    }
    if (ivs['specialAttack'] % 4 > 1) {
      base += 16;
    }
    if (ivs['specialDefense'] % 4 > 1) {
      base += 32;
    }
    return Math.floor(base * (40 / 63) + 30);
  };

  self.BW.type = function(ivs) {
    var value;
    value = 0;
    if (ivs['hp'] % 2 === 1) {
      value += 1;
    }
    if (ivs['attack'] % 2 === 1) {
      value += 2;
    }
    if (ivs['defense'] % 2 === 1) {
      value += 4;
    }
    if (ivs['speed'] % 2 === 1) {
      value += 8;
    }
    if (ivs['specialAttack'] % 2 === 1) {
      value += 16;
    }
    if (ivs['specialDefense'] % 2 === 1) {
      value += 32;
    }
    return self.BW.types[Math.floor(value * 15 / 63)];
  };

  self.BW.ivs = {
    bug: {
      attack: 30,
      defense: 30,
      specialDefense: 30
    },
    dark: {},
    dragon: {
      attack: 30
    },
    electric: {
      specialAttack: 30
    },
    fighting: {
      defense: 30,
      specialAttack: 30,
      specialDefense: 30,
      speed: 30
    },
    fire: {
      attack: 30,
      specialAttack: 30,
      speed: 30
    },
    flying: {
      hp: 30,
      attack: 30,
      defense: 30,
      specialAttack: 30,
      specialDefense: 30
    },
    ghost: {
      defense: 30,
      specialDefense: 30
    },
    grass: {
      attack: 30,
      specialAttack: 30
    },
    ground: {
      specialAttack: 30,
      specialDefense: 30
    },
    ice: {
      attack: 30,
      defense: 30
    },
    poison: {
      defense: 30,
      specialAttack: 30,
      specialDefense: 30
    },
    psychic: {
      attack: 30,
      speed: 30
    },
    rock: {
      defense: 30,
      specialDefense: 30,
      speed: 30
    },
    steel: {
      specialDefense: 30
    },
    water: {
      attack: 30,
      defense: 30,
      specialAttack: 30
    }
  };

}).call(this);

(function() {
  var gen, i, _i, _j, _len, _len1, _ref, _ref1;

  this.ALL_GENERATIONS = ['rb', 'gs', 'rs', 'dp', 'bw', 'xy', 'in'];

  this.SUPPORTED_GENERATIONS = ['xy', 'in'];

  this.DEFAULT_GENERATION = 'in';

  this.INT_TO_GENERATION = {};

  _ref = this.ALL_GENERATIONS;
  for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
    gen = _ref[i];
    this.INT_TO_GENERATION[i + 1] = gen;
  }

  this.GENERATION_TO_INT = {};

  _ref1 = this.ALL_GENERATIONS;
  for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) {
    gen = _ref1[i];
    this.GENERATION_TO_INT[gen] = i + 1;
  }

}).call(this);

(function() {
  var EventPokemon, INT_TO_GENERATION, checkMove, getGenerationFromInt, getMinimumGeneration, loopLearnsets, mustLearnMove, self, switchableFormes, unportableGenerations, unsketchableMoves, _, _ref,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  self = (typeof module !== "undefined" && module !== null ? module.exports : void 0) || window;

  if (typeof module !== "undefined" && module !== null ? module.exports : void 0) {
    EventPokemon = require('./event_pokemon');
    INT_TO_GENERATION = require('./ladders').INT_TO_GENERATION;
    _ = require('underscore')._;
  } else {
    EventPokemon = (_ref = window.EventPokemon) != null ? _ref : {};
    INT_TO_GENERATION = window.INT_TO_GENERATION;
    _ = window._;
  }

  unportableGenerations = [1, 3];

  unportableGenerations.sort(function(a, b) {
    return b - a;
  });

  switchableFormes = ["Deoxys", "Rotom", "Shaymin"];

  unsketchableMoves = ["Chatter", "Hyperspace Hole", "Light of Ruin", "Steam Eruption", "Struggle", "Thousand Arrows", "Thousand Waves"];

  mustLearnMove = {
    "Mamoswine": "AncientPower",
    "Yanmega": "AncientPower",
    "Tangrowth": "AncientPower",
    "Mr. Mime": "Mimic",
    "Sudowoodo": "Mimic",
    "Ambipom": "Double Hit",
    "Lickilicky": "Rollout"
  };

  getMinimumGeneration = function(generation) {
    var minGeneration, unportableGen, _i, _len;
    for (_i = 0, _len = unportableGenerations.length; _i < _len; _i++) {
      unportableGen = unportableGenerations[_i];
      if (unportableGen <= generation) {
        return unportableGen;
      }
    }
    minGeneration = Math.min.apply(Math, unportableGenerations);
    throw new Error("Gen. '" + generation + "' must be greater than " + minGeneration + ".");
  };

  getGenerationFromInt = function(generationInteger) {
    return INT_TO_GENERATION[generationInteger].toUpperCase();
  };

  loopLearnsets = function(Generations, pokemon, forGeneration, iterator) {
    var FormeData, SpeciesData, ability, finalForme, forme, formeName, generation, hasHiddenAbility, learnset, minimumGeneration, species, theFormes, thePokemon, _i, _j, _k, _len, _len1, _ref1;
    minimumGeneration = getMinimumGeneration(forGeneration);
    species = pokemon.species, forme = pokemon.forme, ability = pokemon.ability;
    formeName = forme || "default";
    thePokemon = [];
    theFormes = [formeName];
    _ref1 = Generations[getGenerationFromInt(forGeneration)], SpeciesData = _ref1.SpeciesData, FormeData = _ref1.FormeData;
    finalForme = FormeData[species][formeName];
    while (species) {
      thePokemon.push(species);
      if (__indexOf.call(switchableFormes, species) >= 0 && __indexOf.call(theFormes, species) < 0) {
        theFormes.push.apply(theFormes, (function() {
          var _results;
          _results = [];
          for (forme in FormeData[species]) {
            _results.push(forme);
          }
          return _results;
        })());
      }
      species = SpeciesData[species].evolvedFrom;
    }
    if (ability == null) {
      ability = finalForme.abilities[0];
    }
    hasHiddenAbility = ability === finalForme.hiddenAbility && __indexOf.call(finalForme.abilities, ability) < 0;
    for (_i = 0, _len = thePokemon.length; _i < _len; _i++) {
      species = thePokemon[_i];
      for (_j = 0, _len1 = theFormes.length; _j < _len1; _j++) {
        formeName = theFormes[_j];
        for (generation = _k = minimumGeneration; minimumGeneration <= forGeneration ? _k <= forGeneration : _k >= forGeneration; generation = minimumGeneration <= forGeneration ? ++_k : --_k) {
          FormeData = Generations[getGenerationFromInt(generation)].FormeData;
          if (FormeData[species] == null) {
            continue;
          }
          if (!(formeName in FormeData[species])) {
            formeName = "default";
          }
          forme = FormeData[species][formeName];
          if (!forme.learnset) {
            formeName = "default";
          }
          learnset = forme.learnset;
          if (!learnset) {
            continue;
          }
          if (hasHiddenAbility && (forme.hiddenAbility == null)) {
            continue;
          }
          if (iterator(learnset, species, formeName, generation) === true) {
            return true;
          }
        }
      }
    }
    return false;
  };

  self.learnableMoves = function(Generations, pokemon, forGeneration) {
    var learnable;
    learnable = [];
    loopLearnsets(Generations, pokemon, forGeneration, function(learnset, pokemonSpecies, formeName) {
      var event, events, method, moveName, moves, _i, _len, _ref1, _results;
      events = EventPokemon[pokemonSpecies] || [];
      events = events.filter(function(event) {
        return event.forme === formeName;
      });
      for (_i = 0, _len = events.length; _i < _len; _i++) {
        event = events[_i];
        learnable.push(event.moves);
      }
      for (method in learnset) {
        moves = learnset[method];
        if ((method === 'level-up' || method === 'tutor' || method === 'machine' || method === 'egg') || ((pokemon.forme || "default") === formeName)) {
          learnable.push((function() {
            var _results;
            _results = [];
            for (moveName in moves) {
              _results.push(moveName);
            }
            return _results;
          })());
        }
      }
      if ((_ref1 = learnset["level-up"]) != null ? _ref1["Sketch"] : void 0) {
        _results = [];
        for (moveName in Generations[getGenerationFromInt(forGeneration)].MoveData) {
          if (__indexOf.call(unsketchableMoves, moveName) < 0) {
            _results.push(learnable.push(moveName));
          } else {
            _results.push(void 0);
          }
        }
        return _results;
      }
    });
    return _.chain(learnable).flatten().sort().unique().value();
  };

  self.checkMoveset = function(Generations, pokemon, generation, moves) {
    var FormeData, checksOut, eggMoves, forme, learnset, leftoverMoves, level, looper, lsetLeftovers, m, move, nonstandardGroups, pokemonForme, pokemonLevel, pokemonSpecies, rsForme, _ref1, _ref2, _ref3;
    looper = loopLearnsets.bind(null, Generations, pokemon, generation);
    pokemonSpecies = pokemon.species;
    pokemonForme = pokemon.forme || "default";
    pokemonLevel = pokemon.level || 100;
    FormeData = Generations[getGenerationFromInt(generation)].FormeData;
    forme = FormeData[pokemonSpecies][pokemonForme];
    if (generation === 4) {
      rsForme = ((_ref1 = Generations.DP.FormeData[pokemonSpecies]) != null ? _ref1[pokemonForme] : void 0) || {};
      learnset = ((_ref2 = rsForme.learnset) != null ? _ref2['form-change'] : void 0) || {};
      for (move in learnset) {
        level = learnset[move];
        if (__indexOf.call(moves, move) < 0 || pokemonLevel < level) {
          return false;
        }
      }
    }
    leftoverMoves = (function() {
      var _i, _len, _results;
      _results = [];
      for (_i = 0, _len = moves.length; _i < _len; _i++) {
        m = moves[_i];
        if (!checkMove(looper, pokemon, m)) {
          _results.push(m);
        }
      }
      return _results;
    })();
    learnset = ((_ref3 = forme.learnset) != null ? _ref3['form-change'] : void 0) || {};
    lsetLeftovers = leftoverMoves.filter(function(move) {
      return pokemonLevel >= learnset[move];
    });
    if (lsetLeftovers.length === leftoverMoves.length) {
      return true;
    }
    checksOut = looper(function(learnset, pokemonSpecies, formeName) {
      var event, events, _i, _len;
      events = EventPokemon[pokemonSpecies] || [];
      events = events.filter(function(event) {
        return event.forme === formeName;
      });
      for (_i = 0, _len = events.length; _i < _len; _i++) {
        event = events[_i];
        lsetLeftovers = leftoverMoves.filter(function(move) {
          return __indexOf.call(event.moves, move) >= 0 && pokemonLevel >= event.level;
        });
        if (lsetLeftovers.length === leftoverMoves.length) {
          return true;
        }
      }
    });
    if (checksOut) {
      return true;
    }
    nonstandardGroups = ["light-ball-egg", "stadium-surfing-pikachu"];
    checksOut = looper(function(learnset) {
      var group, total, _i, _len;
      for (_i = 0, _len = nonstandardGroups.length; _i < _len; _i++) {
        group = nonstandardGroups[_i];
        if (!learnset[group]) {
          continue;
        }
        total = ((function() {
          var _j, _len1, _results;
          _results = [];
          for (_j = 0, _len1 = leftoverMoves.length; _j < _len1; _j++) {
            m = leftoverMoves[_j];
            if (m in learnset[group]) {
              _results.push(m);
            }
          }
          return _results;
        })()).length;
        if (total === leftoverMoves.length) {
          return true;
        }
      }
    });
    if (checksOut) {
      return true;
    }
    checksOut = looper(function(learnset) {
      var dreamWorldMoves, moveName;
      if (!learnset['dreamWorld']) {
        return;
      }
      dreamWorldMoves = [];
      for (moveName in learnset['dreamWorld']) {
        if (__indexOf.call(dreamWorldMoves, moveName) >= 0 || __indexOf.call(leftoverMoves, moveName) < 0) {
          continue;
        }
        dreamWorldMoves.push(moveName);
      }
      if (leftoverMoves.length === dreamWorldMoves.length) {
        return true;
      }
    });
    if (checksOut) {
      return true;
    }
    eggMoves = [];
    looper(function(learnset) {
      var moveName, _results;
      if (!learnset['egg']) {
        return;
      }
      _results = [];
      for (moveName in learnset['egg']) {
        if (__indexOf.call(eggMoves, moveName) >= 0 || __indexOf.call(leftoverMoves, moveName) < 0) {
          continue;
        }
        _results.push(eggMoves.push(moveName));
      }
      return _results;
    });
    if (eggMoves.length === 4 && mustLearnMove[pokemon.species]) {
      return false;
    }
    if (eggMoves.length === leftoverMoves.length) {
      return true;
    }
    return false;
  };

  checkMove = function(looper, pokemon, move) {
    var checksOut, level;
    level = pokemon.level;
    level || (level = 100);
    checksOut = looper(function(learnset) {
      var _ref1, _ref2, _ref3, _ref4;
      if (((_ref1 = learnset["level-up"]) != null ? _ref1[move] : void 0) <= level || ((_ref2 = learnset["machine"]) != null ? _ref2[move] : void 0) <= level || ((_ref3 = learnset["tutor"]) != null ? _ref3[move] : void 0) <= level) {
        return true;
      }
      if (((_ref4 = learnset["level-up"]) != null ? _ref4["Sketch"] : void 0) <= level && __indexOf.call(unsketchableMoves, move) < 0) {
        return true;
      }
    });
    if (checksOut) {
      return true;
    }
    return false;
  };

}).call(this);

(function() {
  var BATON_PASS_PBV, self, _base,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  self = (typeof window !== "undefined" && window !== null ? (_base = window.PokeBattle).PBV != null ? _base.PBV : _base.PBV = {} : this);

  BATON_PASS_PBV = 15;

  self.determinePBV = function(genData, pokemonArray) {
    var bpers, forme, item, mega, megaForme, megaSpecies, p, pbv, pokemon, species, speciesData, total, _i, _len, _ref, _ref1;
    if (!(pokemonArray instanceof Array)) {
      pokemonArray = [pokemonArray];
    }
    total = 0;
    for (_i = 0, _len = pokemonArray.length; _i < _len; _i++) {
      pokemon = pokemonArray[_i];
      species = pokemon.species;
      forme = pokemon.forme || "default";
      item = pokemon.item;
      speciesData = genData != null ? genData.FormeData[species] : void 0;
      mega = genData != null ? (_ref = genData.ItemData[item]) != null ? _ref.mega : void 0 : void 0;
      if (mega) {
        megaSpecies = mega[0], megaForme = mega[1];
        if (species === megaSpecies) {
          forme = megaForme;
        }
      }
      pbv = (speciesData != null ? (_ref1 = speciesData[forme]) != null ? _ref1.pokeBattleValue : void 0 : void 0) || 0;
      if (item === 'Eviolite') {
        pbv = Math.round(1.3 * pbv / 5) * 5;
      }
      total += pbv;
    }
    bpers = (function() {
      var _j, _len1, _results;
      _results = [];
      for (_j = 0, _len1 = pokemonArray.length; _j < _len1; _j++) {
        p = pokemonArray[_j];
        if (__indexOf.call(p.moves || [], "Baton Pass") >= 0) {
          _results.push(p);
        }
      }
      return _results;
    })();
    if (bpers.length > 0) {
      total += BATON_PASS_PBV * Math.pow(2, bpers.length - 1);
    }
    return total;
  };

}).call(this);

(function() {
  this.Protocol = {
    CHANGE_HP: 1,
    SWITCH_IN: 2,
    CHANGE_PP: 3,
    REQUEST_ACTIONS: 4,
    START_TURN: 5,
    RAW_MESSAGE: 6,
    FAINT: 7,
    MAKE_MOVE: 8,
    END_BATTLE: 9,
    FORFEIT_BATTLE: 10,
    MOVE_SUCCESS: 11,
    SWITCH_OUT: 12,
    POKEMON_ATTACH: 13,
    TEAM_ATTACH: 14,
    BATTLE_ATTACH: 15,
    POKEMON_UNATTACH: 16,
    TEAM_UNATTACH: 17,
    BATTLE_UNATTACH: 18,
    START_BATTLE: 19,
    RECEIVE_TEAM: 20,
    CHANGE_EXACT_HP: 21,
    SPRITE_CHANGE: 22,
    BOOSTS: 23,
    RESET_BOOSTS: 24,
    MOVESET_UPDATE: 26,
    TEAM_PREVIEW: 27,
    INITIALIZE: 28,
    REARRANGE_TEAMS: 29,
    TIMER_WIN: 30,
    WEATHER_CHANGE: 32,
    ACTIVATE_ABILITY: 35,
    CANNED_TEXT: 36,
    CONTINUE_TURN: 37,
    BATTLE_EXPIRED: 38,
    SET_BOOSTS: 39,
    END_MOVE: 40,
    NAME_CHANGE: 41,
    ILLUSION_CHANGE: 42,
    VISIBLE_TEAM: 43
  };

}).call(this);

(function() {
  var Tiers, actualtiers, conditions, self, _, _base, _ref;

  self = (typeof window !== "undefined" && window !== null ? (_base = window.PokeBattle).Tier != null ? _base.Tier : _base.Tier = {} : this);

  if (typeof window === "undefined" || window === null) {
    Tiers = require('./conditions').Tiers;
    _ = require('underscore')._;
    actualtiers = Tiers;
  } else {
    conditions = (_ref = window.conditions) != null ? _ref : {};
    actualtiers = Tiers;
    _ = window._;
  }

  self.Tiers = {
    Unsorted: {
      name: "Unsorted",
      humanName: "Unsorted",
      tierRank: -1,
      playable: false
    },
    PA: {
      name: "PA",
      humanName: "Pathetic",
      tierRank: 0,
      playable: false
    },
    LC: {
      name: "LC",
      humanName: "Little Cup",
      tierRank: 1,
      playable: false
    },
    PU: {
      name: "PU",
      humanName: "Poorly Used",
      tierRank: 2,
      playable: false
    },
    NU: {
      name: "NU",
      humanName: "Never Used",
      tierRank: 3,
      playable: false
    },
    RU: {
      name: "RU",
      humanName: "Rarely Used",
      tierRank: 4,
      playable: false
    },
    UU: {
      name: "UU",
      humanName: "Under Used",
      tierRank: 5,
      playable: true,
      priority: 1
    },
    OU: {
      name: "OU",
      humanName: "Over Used",
      tierRank: 6,
      playable: true,
      priority: 0
    },
    Uber: {
      name: "Uber",
      humanName: "Ubers",
      tierRank: 7,
      playable: true,
      priority: 2
    },
    AG: {
      name: "AG",
      humanName: "Anything Goes",
      tierRank: 8,
      playable: false
    }
  };

  self.determineTier = function(genData, pokemonArray) {
    var actualtier, forme, item, mega, megaForme, megaSpecies, pokemon, species, speciesData, tier, tierdata, tierrank, _i, _len, _ref1, _ref2;
    actualtiers = this.Tiers;
    if (!(pokemonArray instanceof Array)) {
      pokemonArray = [pokemonArray];
    }
    tierrank = -1;
    for (_i = 0, _len = pokemonArray.length; _i < _len; _i++) {
      pokemon = pokemonArray[_i];
      species = pokemon.species;
      forme = pokemon.forme || "default";
      item = pokemon.item;
      speciesData = genData != null ? genData.FormeData[species] : void 0;
      mega = genData != null ? (_ref1 = genData.ItemData[item]) != null ? _ref1.mega : void 0 : void 0;
      if (mega) {
        megaSpecies = mega[0], megaForme = mega[1];
        if (species === megaSpecies) {
          forme = megaForme;
        }
      }
      tier = (speciesData != null ? (_ref2 = speciesData[forme]) != null ? _ref2.tier[0] : void 0 : void 0) || 'Unsorted';
      tierdata = actualtiers[tier];
      if (typeof tierdata === 'undefined') {
        tierdata = actualtiers['Unsorted'];
      }
      if (tierdata.tierRank > tierrank) {
        tierrank = tierdata.tierRank;
      }
    }
    actualtier = _.findWhere(actualtiers, {
      tierRank: tierrank
    });
    return actualtier;
  };

}).call(this);

(function() {
  var self;

  self = (typeof module !== "undefined" && module !== null ? module.exports : void 0) || window;

  self.Weather = {
    SUN: 'Sun',
    RAIN: 'Rain',
    HAIL: 'Hail',
    SAND: 'Sand',
    NONE: 'None',
    MOON: 'Moon',
    DELTASTREAM: 'DeltaStream',
    HARSHSUN: 'HarshSun'
  };

}).call(this);

(function() {
  var _base;

  if (this.PokeBattle == null) {
    this.PokeBattle = {};
  }

  if ((_base = this.PokeBattle).mixins == null) {
    _base.mixins = {};
  }

}).call(this);

(function() {
  var __slice = [].slice;

  this.PokeBattle.mixins.BattleProtocolParser = {
    update: function(actions) {
      var hadStuff, _ref;
      if (actions.length === 0) {
        return;
      }
      this.notify();
      hadStuff = this.updateQueue.length > 0;
      (_ref = this.updateQueue).push.apply(_ref, actions);
      if (!hadStuff) {
        return this._update();
      }
    },
    _update: function(wasAtBottom) {
      var ability, action, arrangements, attachment, boosts, cannedInteger, change, deltaBoosts, done, doneSpeedTimeout, doneTimeout, e, effect, forfeiter, fromSlot, key, message, moveIndex, moveName, movesetJSON, newForme, newHP, newName, newPP, newPercent, newSpecies, newWeather, player, pokemon, protocol, queue, rest, slot, targetSlots, team, teams, toSlot, turn, type, validActions, value, view, winner, _ref;
      view = this.view;
      queue = this.updateQueue;
      if (!queue) {
        return;
      }
      if (queue.length === 0) {
        view.renderUserInfo();
        view.resetPopovers();
        if (wasAtBottom || (view.skip != null)) {
          view.chatView.scrollToBottom();
        }
        if (view.skip != null) {
          delete view.skip;
          view.$('.battle_pane').show();
        }
        return;
      }
      wasAtBottom || (wasAtBottom = view.chatView.isAtBottom());
      action = queue.shift();
      type = action[0], rest = 2 <= action.length ? __slice.call(action, 1) : [];
      protocol = ((function() {
        var _results;
        _results = [];
        for (key in Protocol) {
          value = Protocol[key];
          if (value === type) {
            _results.push(key);
          }
        }
        return _results;
      })())[0];
      try {
        if (window.localStorage.debug === 'true') {
          console.log("Received protocol: " + protocol + " with args: " + rest);
        }
      } catch (_error) {

      }
      done = (function(_this) {
        return function() {
          if (done.called) {
            return;
          }
          done.called = true;
          if (view.skip != null) {
            return _this._update.call(_this, wasAtBottom);
          } else {
            return setTimeout(_this._update.bind(_this, wasAtBottom), 0);
          }
        };
      })(this);
      doneTimeout = function() {
        return setTimeout(done, 0);
      };
      doneSpeedTimeout = (function(_this) {
        return function() {
          if ((view.skip != null) || view.speed <= 1) {
            return done();
          } else {
            return setTimeout(done, (view.speed - 1) * 1000);
          }
        };
      })(this);
      try {
        switch (type) {
          case Protocol.CHANGE_HP:
            player = rest[0], slot = rest[1], newPercent = rest[2];
            pokemon = this.getPokemon(player, slot);
            pokemon.set('percent', newPercent);
            if (view.skip != null) {
              done();
            } else {
              setTimeout(done, 500);
            }
            break;
          case Protocol.CHANGE_EXACT_HP:
            player = rest[0], slot = rest[1], newHP = rest[2];
            pokemon = this.getPokemon(player, slot);
            pokemon.set('hp', newHP);
            done();
            break;
          case Protocol.SWITCH_OUT:
            player = rest[0], slot = rest[1];
            view.switchOut(player, slot, done);
            break;
          case Protocol.SWITCH_IN:
            player = rest[0], toSlot = rest[1], fromSlot = rest[2];
            team = this.getTeam(player).get('pokemon').models;
            _ref = [team[fromSlot], team[toSlot]], team[toSlot] = _ref[0], team[fromSlot] = _ref[1];
            view.switchIn(player, toSlot, fromSlot, doneSpeedTimeout);
            break;
          case Protocol.CHANGE_PP:
            player = rest[0], slot = rest[1], moveIndex = rest[2], newPP = rest[3];
            pokemon = this.getPokemon(player, slot);
            pokemon.setPP(moveIndex, newPP);
            done();
            break;
          case Protocol.REQUEST_ACTIONS:
            validActions = rest[0];
            view.enableButtons(validActions);
            PokeBattle.notifyUser(PokeBattle.NotificationTypes.ACTION_REQUESTED, this.id + "_" + this.get('turn'));
            done();
            break;
          case Protocol.START_TURN:
            turn = rest[0];
            view.beginTurn(turn, doneTimeout);
            break;
          case Protocol.CONTINUE_TURN:
            view.continueTurn(doneTimeout);
            break;
          case Protocol.RAW_MESSAGE:
            message = rest[0];
            view.addLog("" + message + "<br>");
            done();
            break;
          case Protocol.FAINT:
            player = rest[0], slot = rest[1];
            view.faint(player, slot, done);
            break;
          case Protocol.MAKE_MOVE:
            player = rest[0], slot = rest[1], moveName = rest[2];
            view.logMove(player, slot, moveName, done);
            break;
          case Protocol.END_BATTLE:
            winner = rest[0];
            view.announceWinner(winner, done);
            break;
          case Protocol.FORFEIT_BATTLE:
            forfeiter = rest[0];
            view.announceForfeit(forfeiter, done);
            break;
          case Protocol.TIMER_WIN:
            winner = rest[0];
            view.announceTimer(winner, done);
            break;
          case Protocol.BATTLE_EXPIRED:
            view.announceExpiration(done);
            break;
          case Protocol.MOVE_SUCCESS:
            player = rest[0], slot = rest[1], targetSlots = rest[2], moveName = rest[3];
            view.moveSuccess(player, slot, targetSlots, moveName, done);
            break;
          case Protocol.CANNED_TEXT:
            cannedInteger = rest.splice(0, 1);
            view.parseCannedText(cannedInteger, rest, done);
            break;
          case Protocol.EFFECT_END:
            player = rest[0], slot = rest[1], effect = rest[2];
            view.endEffect(player, slot, effect, done);
            break;
          case Protocol.POKEMON_ATTACH:
            player = rest[0], slot = rest[1], attachment = rest[2];
            view.attachPokemon(player, slot, attachment, done);
            break;
          case Protocol.TEAM_ATTACH:
            player = rest[0], attachment = rest[1];
            view.attachTeam(player, attachment, done);
            break;
          case Protocol.BATTLE_ATTACH:
            attachment = rest[0];
            view.attachBattle(attachment, done);
            break;
          case Protocol.POKEMON_UNATTACH:
            player = rest[0], slot = rest[1], attachment = rest[2];
            view.unattachPokemon(player, slot, attachment, done);
            break;
          case Protocol.TEAM_UNATTACH:
            player = rest[0], attachment = rest[1];
            view.unattachTeam(player, attachment, done);
            break;
          case Protocol.BATTLE_UNATTACH:
            attachment = rest[0];
            view.unattachBattle(attachment, done);
            break;
          case Protocol.INITIALIZE:
            teams = rest[0];
            this.receiveTeams(teams);
            view.preloadImages();
            if (!this.get('spectating')) {
              PokeBattle.notifyUser(PokeBattle.NotificationTypes.BATTLE_STARTED, this.id);
            }
            done();
            break;
          case Protocol.START_BATTLE:
            view.removeTeamPreview();
            view.renderBattle();
            done();
            break;
          case Protocol.REARRANGE_TEAMS:
            arrangements = rest;
            this.get('teams').forEach(function(team, i) {
              return team.rearrange(arrangements[i]);
            });
            done();
            break;
          case Protocol.RECEIVE_TEAM:
            team = rest[0];
            this.receiveTeam(team);
            done();
            break;
          case Protocol.SPRITE_CHANGE:
            player = rest[0], slot = rest[1], newSpecies = rest[2], newForme = rest[3];
            pokemon = this.getPokemon(player, slot);
            pokemon.set('species', newSpecies);
            pokemon.set('forme', newForme);
            view.changeSprite(player, slot, newSpecies, newForme, done);
            break;
          case Protocol.NAME_CHANGE:
            player = rest[0], slot = rest[1], newName = rest[2];
            pokemon = this.getPokemon(player, slot);
            view.changeName(player, slot, newName, done);
            break;
          case Protocol.BOOSTS:
            player = rest[0], slot = rest[1], deltaBoosts = rest[2];
            view.boost(player, slot, deltaBoosts, {
              floatText: true
            });
            done();
            break;
          case Protocol.SET_BOOSTS:
            player = rest[0], slot = rest[1], boosts = rest[2];
            view.setBoosts(player, slot, boosts);
            done();
            break;
          case Protocol.RESET_BOOSTS:
            player = rest[0], slot = rest[1];
            view.resetBoosts(player, slot);
            done();
            break;
          case Protocol.MOVESET_UPDATE:
            player = rest[0], slot = rest[1], movesetJSON = rest[2];
            pokemon = this.getPokemon(player, slot);
            pokemon.set(movesetJSON);
            done();
            break;
          case Protocol.WEATHER_CHANGE:
            newWeather = rest[0];
            view.changeWeather(newWeather, done);
            break;
          case Protocol.TEAM_PREVIEW:
            view.renderTeamPreview();
            done();
            break;
          case Protocol.ACTIVATE_ABILITY:
            player = rest[0], slot = rest[1], ability = rest[2];
            pokemon = this.getPokemon(player, slot);
            pokemon.set('ability', ability);
            view.activateAbility(player, slot, ability, done);
            break;
          case Protocol.END_MOVE:
            doneSpeedTimeout();
            break;
          case Protocol.ILLUSION_CHANGE:
            player = rest[0], slot = rest[1], change = rest[2];
            pokemon = this.getPokemon(player, slot);
            pokemon.setIllu(change);
            done();
            break;
          case Protocol.VISIBLE_TEAM:
            view.setVisibleTeam();
            break;
          default:
            done();
        }
      } catch (_error) {
        e = _error;
        console.error(e);
        console.error(e.stack);
        done();
      }
      if (wasAtBottom && !view.chatView.isAtBottom()) {
        return view.chatView.scrollToBottom();
      }
    }
  };

}).call(this);

(function() {
  var MINUS, PLUS, natures, statAbbreviations,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  this.Pokemon = (function(_super) {
    __extends(Pokemon, _super);

    function Pokemon() {
      this.getTeam = __bind(this.getTeam, this);
      this.defaults = __bind(this.defaults, this);
      return Pokemon.__super__.constructor.apply(this, arguments);
    }

    Pokemon.prototype.defaults = function() {
      return {
        moves: [],
        percent: 100,
        ivs: {
          hp: 31,
          attack: 31,
          defense: 31,
          specialAttack: 31,
          specialDefense: 31,
          speed: 31
        },
        evs: {
          hp: 0,
          attack: 0,
          defense: 0,
          specialAttack: 0,
          specialDefense: 0,
          speed: 0
        }
      };
    };

    Pokemon.prototype.initialize = function(attributes) {
      var genders, hiddenPowerType;
      if (attributes == null) {
        attributes = {};
      }
      if (!this.has('species') && this.has('name')) {
        this.set('species', this.get('name'));
      }
      if (!this.has('forme')) {
        this.set('forme', 'default');
      }
      this.set('illu', false);
      this.normalizeStats(this.get('ivs'), 31);
      this.normalizeStats(this.get('evs'), 0);
      this.resetBoosts();
      this.isNull = false;
      if (this.get('teambuilder') !== true) {
        return;
      }
      this.on('change:ivs', (function(_this) {
        return function(model, ivs) {
          var type;
          type = HiddenPower.BW.type(ivs).toLowerCase();
          return _this.set("hiddenPowerType", type, {
            silent: true
          });
        };
      })(this));
      this.on('change:hiddenPowerType', (function(_this) {
        return function(model, type) {
          var hpIVs, iv, ivs, stat;
          hpIVs = HiddenPower.BW.ivs[type.toLowerCase()];
          ivs = _this.get('ivs');
          for (stat in ivs) {
            iv = ivs[stat];
            ivs[stat] = hpIVs[stat] || 31;
          }
          return _this.set('ivs', ivs, {
            silent: true
          });
        };
      })(this));
      if (!attributes.ability) {
        this.set('ability', this.getAbilities()[0]);
      }
      if (!attributes.level) {
        this.set('level', 100);
      }
      if (isNaN(attributes.happiness)) {
        this.set('happiness', 100);
      }
      if (!attributes.nature) {
        this.set('nature', 'Hardy');
      }
      hiddenPowerType = HiddenPower.BW.type(this.get('ivs')).toLowerCase();
      this.set('hiddenPowerType', hiddenPowerType, {
        silent: true
      });
      if (!this.has('gender')) {
        genders = this.getGenders();
        if (genders.length === 1) {
          return this.set('gender', genders[0], {
            silent: true
          });
        }
      }
    };

    Pokemon.prototype.resetBoosts = function() {
      return this.set('stages', {
        hp: 0,
        attack: 0,
        defense: 0,
        specialAttack: 0,
        specialDefense: 0,
        speed: 0,
        accuracy: 0,
        evasion: 0
      });
    };

    Pokemon.prototype.normalizeStats = function(hash, defaultValue) {
      var stat, stats, _i, _len, _results;
      stats = ["hp", "attack", "defense", "specialAttack", "specialDefense", "speed"];
      _results = [];
      for (_i = 0, _len = stats.length; _i < _len; _i++) {
        stat = stats[_i];
        _results.push(hash[stat] != null ? hash[stat] : hash[stat] = defaultValue);
      }
      return _results;
    };

    Pokemon.prototype.getName = function() {
      var sanitizedName;
      sanitizedName = $('<div/>').text(this.get('name')).html();
      sanitizedName = sanitizedName.replace(/[\u0300-\u036F\u20D0-\u20FF\uFE20-\uFE2F]/g, '');
      return sanitizedName;
    };

    Pokemon.prototype.getGeneration = function(generation) {
      var gen, _ref;
      gen = generation || ((_ref = this.collection) != null ? _ref.generation : void 0) || DEFAULT_GENERATION;
      gen = gen.toUpperCase();
      return window.Generations[gen];
    };

    Pokemon.prototype.getSpecies = function() {
      return this.getGeneration().SpeciesData[this.get('species')];
    };

    Pokemon.prototype.getItem = function() {
      return this.getGeneration().ItemData[this.get('item')];
    };

    Pokemon.prototype.getForme = function(forme, generation) {
      var _ref;
      forme || (forme = this.get('forme'));
      return (_ref = this.getGeneration(generation).FormeData[this.get('species')]) != null ? _ref[forme] : void 0;
    };

    Pokemon.prototype.getFormes = function() {
      var forme, _results;
      _results = [];
      for (forme in this.getGeneration().FormeData[this.get('species')]) {
        _results.push(forme);
      }
      return _results;
    };

    Pokemon.prototype.getSelectableFormes = function() {
      return _(this.getFormes()).reject((function(_this) {
        return function(forme) {
          return _this.getForme(forme).isBattleOnly;
        };
      })(this));
    };

    Pokemon.prototype.getMegaFormes = function() {
      return _(this.getFormes()).reject((function(_this) {
        return function(forme) {
          return forme.indexOf('mega') !== 0;
        };
      })(this));
    };

    Pokemon.prototype.getAbilities = function() {
      var abilities, forme;
      forme = this.getForme();
      abilities = _.clone(forme.abilities);
      if (forme.hiddenAbility) {
        abilities.push(forme.hiddenAbility);
      }
      return _.unique(abilities);
    };

    Pokemon.prototype.getGenders = function() {
      var genders, species;
      species = this.getSpecies();
      genders = [];
      switch (species.genderRatio) {
        case -1:
          genders.push("Genderless");
          break;
        case 0:
          genders.push("M");
          break;
        case 8:
          genders.push("F");
          break;
        default:
          genders.push("M", "F");
      }
      return genders;
    };

    Pokemon.prototype.hasSelectedMove = function(moveName) {
      return moveName && __indexOf.call(this.moves, moveName) >= 0;
    };

    Pokemon.prototype.getMovepool = function() {
      var MoveData, SpeciesData, generation, learnset, _ref, _ref1;
      _ref = this.getGeneration(), SpeciesData = _ref.SpeciesData, MoveData = _ref.MoveData;
      generation = GENERATION_TO_INT[((_ref1 = this.collection) != null ? _ref1.generation : void 0) || DEFAULT_GENERATION];
      learnset = learnableMoves(window.Generations, this.attributes, generation);
      return _(learnset).map(function(moveName) {
        var move;
        move = _(MoveData[moveName]).clone();
        move['name'] = moveName;
        return move;
      });
    };

    Pokemon.prototype.getTotalEVs = function(options) {
      var stat, total, value, _ref;
      if (options == null) {
        options = {};
      }
      total = 0;
      _ref = this.get("evs");
      for (stat in _ref) {
        value = _ref[stat];
        if (stat !== options.exclude) {
          total += value;
        }
      }
      return total;
    };

    Pokemon.prototype.getTeam = function() {
      var _ref;
      return (_ref = this.collection) != null ? _ref.parents[0] : void 0;
    };

    Pokemon.prototype.setIv = function(stat, value) {
      var ivs;
      ivs = _.clone(this.get("ivs"));
      ivs[stat] = value;
      return this.set("ivs", ivs);
    };

    Pokemon.prototype.setEv = function(stat, value) {
      var evs;
      evs = _.clone(this.get("evs"));
      value = value - (value % 4);
      evs[stat] = value;
      this.set("evs", evs);
      return value;
    };

    Pokemon.prototype.iv = function(stat) {
      var _ref;
      return (_ref = this.get("ivs")[stat]) != null ? _ref : 31;
    };

    Pokemon.prototype.ev = function(stat) {
      var _ref;
      return (_ref = this.get("evs")[stat]) != null ? _ref : 0;
    };

    Pokemon.prototype.natureBoost = function(stat) {
      var nature, _ref;
      nature = (_ref = this.get('nature')) != null ? _ref.toLowerCase() : void 0;
      if (nature in natures) {
        return natures[nature][stat] || 1;
      } else {
        return 1;
      }
    };

    Pokemon.prototype.base = function(key) {
      var base, forme;
      forme = this.getForme();
      return base = forme["stats"][key];
    };

    Pokemon.prototype.stat = function(key) {
      var base, ev, iv, level, total;
      base = this.base(key);
      if (base === 1) {
        return 1;
      }
      level = this.get('level') || 100;
      iv = this.iv(key);
      ev = Math.floor(this.ev(key) / 4);
      return total = key === 'hp' ? Math.floor((2 * base + iv + ev) * (level / 100) + level + 10) : Math.floor(((2 * base + iv + ev) * (level / 100) + 5) * this.natureBoost(key));
    };

    Pokemon.prototype.getNatures = function() {
      var invertedStats, label, minusStat, name, nature, natureResults, plusStat, stats;
      natureResults = [];
      for (nature in natures) {
        stats = natures[nature];
        name = nature[0].toUpperCase() + nature.substr(1);
        invertedStats = _(stats).invert();
        label = name;
        if (invertedStats[PLUS]) {
          plusStat = statAbbreviations[invertedStats[PLUS]];
          minusStat = statAbbreviations[invertedStats[MINUS]];
          label = "" + name + " (+" + plusStat + ", -" + minusStat + ")";
        }
        natureResults.push([name, label]);
      }
      return natureResults;
    };

    Pokemon.prototype.getPBV = function() {
      var gen;
      gen = this.getGeneration();
      return PokeBattle.PBV.determinePBV(gen, this.attributes);
    };

    Pokemon.prototype.getTier = function() {
      var gen;
      gen = this.getGeneration();
      return PokeBattle.Tier.determineTier(gen, this.attributes);
    };

    Pokemon.prototype.setPP = function(moveIndex, newPP) {
      var array;
      array = _.clone(this.get('pp'));
      array[moveIndex] = newPP;
      return this.set('pp', array);
    };

    Pokemon.prototype.getPercentHP = function() {
      return Math.max(this.get('percent'), 0);
    };

    Pokemon.prototype.getHPColor = function() {
      var percent;
      percent = this.getPercentHP();
      switch (false) {
        case !(percent <= 20):
          return 'red';
        case !(percent <= 50):
          return 'yellow';
        default:
          return 'green';
      }
    };

    Pokemon.prototype.isFainted = function() {
      return this.get('percent') <= 0;
    };

    Pokemon.prototype.getStatus = function() {
      var status;
      status = this.get('status');
      if (status) {
        return "" + (status[0].toUpperCase()) + (status.substr(1));
      } else {
        return "Healthy";
      }
    };

    Pokemon.prototype.canMegaEvolve = function() {
      var forme, item, species, _ref;
      item = this.getItem();
      if (item.type !== 'megastone') {
        return false;
      }
      _ref = item.mega, species = _ref[0], forme = _ref[1];
      if (this.get('species') !== species || this.get('forme') !== 'default') {
        return false;
      }
      return true;
    };

    Pokemon.prototype.getPossibleMegaForme = function() {
      var forme, item, species, _ref;
      item = this.getItem();
      if ((item != null ? item.type : void 0) !== 'megastone') {
        return null;
      }
      _ref = item.mega, species = _ref[0], forme = _ref[1];
      if (this.get('species') === species && this.get('forme') === 'default') {
        return forme;
      }
      return null;
    };

    Pokemon.prototype.getPokedexUrl = function() {
      var slugForme, slugSpecies, slugify;
      slugify = function(str) {
        return str.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/\-{2,}/g, '-');
      };
      slugSpecies = slugify(this.get('species'));
      slugForme = slugify(this.get('forme'));
      return "//pokebattle.com/dex/pokemon/" + slugSpecies + "/" + slugForme;
    };

    Pokemon.prototype.getIllu = function() {
      return this.get('illu');
    };

    Pokemon.prototype.setIllu = function(y) {
      return this.set('illu', y);
    };

    Pokemon.prototype.toJSON = function() {
      var attributes;
      attributes = _.clone(this.attributes);
      if (attributes.gender === 'Genderless') {
        delete attributes.gender;
      }
      delete attributes.hiddenPowerType;
      delete attributes.teambuilder;
      return attributes;
    };

    return Pokemon;

  })(Backbone.Model);

  statAbbreviations = {
    'hp': 'HP',
    'attack': 'Atk',
    'defense': 'Def',
    'specialAttack': 'SAtk',
    'specialDefense': 'SDef',
    'speed': 'Spe'
  };

  PLUS = 1.1;

  MINUS = 0.9;

  natures = {
    lonely: {
      attack: PLUS,
      defense: MINUS
    },
    brave: {
      attack: PLUS,
      speed: MINUS
    },
    adamant: {
      attack: PLUS,
      specialAttack: MINUS
    },
    naughty: {
      attack: PLUS,
      specialDefense: MINUS
    },
    bold: {
      defense: PLUS,
      attack: MINUS
    },
    relaxed: {
      defense: PLUS,
      speed: MINUS
    },
    impish: {
      defense: PLUS,
      specialAttack: MINUS
    },
    lax: {
      defense: PLUS,
      specialDefense: MINUS
    },
    timid: {
      speed: PLUS,
      attack: MINUS
    },
    hasty: {
      speed: PLUS,
      defense: MINUS
    },
    jolly: {
      speed: PLUS,
      specialAttack: MINUS
    },
    naive: {
      speed: PLUS,
      specialDefense: MINUS
    },
    modest: {
      specialAttack: PLUS,
      attack: MINUS
    },
    mild: {
      specialAttack: PLUS,
      defense: MINUS
    },
    quiet: {
      specialAttack: PLUS,
      speed: MINUS
    },
    rash: {
      specialAttack: PLUS,
      specialDefense: MINUS
    },
    calm: {
      specialDefense: PLUS,
      attack: MINUS
    },
    gentle: {
      specialDefense: PLUS,
      defense: MINUS
    },
    sassy: {
      specialDefense: PLUS,
      speed: MINUS
    },
    careful: {
      specialDefense: PLUS,
      specialAttack: MINUS
    },
    hardy: {},
    docile: {},
    serious: {},
    bashful: {},
    quirky: {}
  };

  this.NullPokemon = (function(_super) {
    __extends(NullPokemon, _super);

    function NullPokemon() {
      return NullPokemon.__super__.constructor.apply(this, arguments);
    }

    NullPokemon.prototype.initialize = function() {
      this.set('species', null);
      this.set('forme', 'default');
      return this.isNull = true;
    };

    NullPokemon.prototype.getNatures = function() {
      return [];
    };

    NullPokemon.prototype.getPBV = function() {
      return 0;
    };

    NullPokemon.prototype.base = function() {
      return 0;
    };

    NullPokemon.prototype.stat = function() {
      return null;
    };

    NullPokemon.prototype.iv = function() {
      return null;
    };

    NullPokemon.prototype.ev = function() {
      return null;
    };

    NullPokemon.prototype.getSpecies = function() {
      return {
        id: 0,
        genderRatio: -1,
        generation: 1
      };
    };

    NullPokemon.prototype.getForme = function() {
      return this.getFormes()['default'];
    };

    NullPokemon.prototype.getFormes = function() {
      return {
        "default": {
          abilities: [],
          hiddenAbility: null,
          isBattleOnly: false,
          learnset: {},
          types: []
        }
      };
    };

    return NullPokemon;

  })(Pokemon);

}).call(this);

(function() {
  var PokemonCollection,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  PokemonCollection = (function(_super) {
    __extends(PokemonCollection, _super);

    function PokemonCollection() {
      this.model = __bind(this.model, this);
      return PokemonCollection.__super__.constructor.apply(this, arguments);
    }

    PokemonCollection.prototype.model = function(attrs, options) {
      if (attrs.name || attrs.species) {
        attrs.teambuilder = this.parents[0].get('teambuilder');
        return new Pokemon(attrs, options);
      } else {
        return new NullPokemon();
      }
    };

    return PokemonCollection;

  })(Backbone.Collection);

  this.Team = (function(_super) {
    __extends(Team, _super);

    function Team() {
      this.setRandomOrder = __bind(this.setRandomOrder, this);
      this.getRandomOrder = __bind(this.getRandomOrder, this);
      this.sync = __bind(this.sync, this);
      this.hasNonNullPokemon = __bind(this.hasNonNullPokemon, this);
      this.getNonNullPokemon = __bind(this.getNonNullPokemon, this);
      this.getMaxTier = __bind(this.getMaxTier, this);
      this.getMaxTierName = __bind(this.getMaxTierName, this);
      this.hasTier = __bind(this.hasTier, this);
      this.hasPBV = __bind(this.hasPBV, this);
      this.getMaxPBV = __bind(this.getMaxPBV, this);
      this.getTier = __bind(this.getTier, this);
      this.getPBV = __bind(this.getPBV, this);
      this.getFormat = __bind(this.getFormat, this);
      this.clone = __bind(this.clone, this);
      this.toNonNullJSON = __bind(this.toNonNullJSON, this);
      this.replace = __bind(this.replace, this);
      this.indexOf = __bind(this.indexOf, this);
      this.at = __bind(this.at, this);
      this.toJSON = __bind(this.toJSON, this);
      this.getName = __bind(this.getName, this);
      this.initialize = __bind(this.initialize, this);
      return Team.__super__.constructor.apply(this, arguments);
    }

    Team.prototype.relations = [
      {
        type: Backbone.Many,
        key: 'pokemon',
        collectionType: PokemonCollection
      }
    ];

    Team.prototype.initialize = function(attrs, options) {
      if (attrs == null) {
        attrs = {};
      }
      if (options == null) {
        options = {};
      }
      this.owner = attrs.owner;
      if (!attrs.generation) {
        this.set('generation', DEFAULT_GENERATION);
      }
      if (options.teambuilder) {
        this.set('teambuilder', true);
      }
      if (!attrs.pokemon) {
        return this.set('pokemon', []);
      }
    };

    Team.prototype.getName = function() {
      return this.get('name') || "Untitled team";
    };

    Team.prototype.toJSON = function() {
      var json;
      json = {};
      if (this.id) {
        json['id'] = this.id;
      }
      json['name'] = this.get('name');
      json['generation'] = this.get('generation');
      json['pokemon'] = this.get('pokemon').toJSON();
      return json;
    };

    Team.prototype.at = function(idx) {
      return this.get('pokemon').at(idx);
    };

    Team.prototype.indexOf = function(idx) {
      return this.get('pokemon').indexOf(idx);
    };

    Team.prototype.replace = function(idx, newPokemon) {
      this.get('pokemon').remove(this.get('pokemon').at(idx));
      return this.get('pokemon').add(newPokemon, {
        at: idx
      });
    };

    Team.prototype.toNonNullJSON = function() {
      return {
        id: this.id,
        name: this.get('name'),
        generation: this.get('generation'),
        pokemon: this.get('pokemon').reject(function(pokemon) {
          return pokemon.isNull;
        }).map(function(pokemon) {
          return pokemon.toJSON();
        })
      };
    };

    Team.prototype.clone = function() {
      var attrs;
      attrs = _(this.attributes).clone();
      attrs.pokemon = this.get('pokemon').toJSON();
      return new Team(attrs);
    };

    Team.prototype.rearrange = function(arrangement) {
      var index, pokemon;
      pokemon = this.get('pokemon');
      pokemon.reset((function() {
        var _i, _len, _results;
        _results = [];
        for (_i = 0, _len = arrangement.length; _i < _len; _i++) {
          index = arrangement[_i];
          _results.push(pokemon.models[index]);
        }
        return _results;
      })());
      return true;
    };

    Team.prototype.getFormat = function() {
      var allformats, format;
      format = this.get('generation');
      allformats = window.PokeBattle.conditions.Formats();
      if (!(format in allformats)) {
        format = DEFAULT_FORMAT;
      }
      return allformats[format];
    };

    Team.prototype.getGeneration = function(generation) {
      var gen;
      gen = generation || this.getFormat().generation;
      gen = gen.toUpperCase();
      return window.Generations[gen];
    };

    Team.prototype.getPBV = function() {
      var gen, pokemon;
      gen = this.getGeneration();
      pokemon = this.get('pokemon').toJSON();
      return PokeBattle.PBV.determinePBV(gen, pokemon);
    };

    Team.prototype.getTier = function() {
      var gen, pokemon;
      gen = this.getGeneration();
      pokemon = this.get('pokemon').toJSON();
      return PokeBattle.Tier.determineTier(gen, pokemon);
    };

    Team.prototype.getMaxPBV = function() {
      var conditions, _ref, _ref1;
      conditions = this.getFormat().conditions;
      if (_ref = Conditions.PBV_1000, __indexOf.call(conditions, _ref) >= 0) {
        return 1000;
      } else if (_ref1 = Conditions.PBV_500, __indexOf.call(conditions, _ref1) >= 0) {
        return 500;
      } else {
        return 0;
      }
    };

    Team.prototype.hasPBV = function() {
      return this.getMaxPBV() > 0;
    };

    Team.prototype.hasTier = function() {
      return typeof this.getMaxTier() !== 'undefined';
    };

    Team.prototype.getMaxTierName = function() {
      var condition, conditions, tier, tiername, _i, _len;
      conditions = this.getFormat().conditions;
      for (_i = 0, _len = conditions.length; _i < _len; _i++) {
        condition = conditions[_i];
        tiername = _.invert(Conditions)[condition];
        if ((tiername.search(/TIER_/)) === 0) {
          tier = tiername.replace(/TIER_/, "");
        }
      }
      return tier;
    };

    Team.prototype.getMaxTier = function() {
      var tier, tiername;
      tiername = this.getMaxTierName();
      if (tiername) {
        tier = PokeBattle.Tier.Tiers[tiername];
      }
      return tier;
    };

    Team.prototype.getNonNullPokemon = function() {
      return this.get('pokemon').where({
        isNull: false
      });
    };

    Team.prototype.hasNonNullPokemon = function() {
      return this.get('pokemon').some(function(pokemon) {
        return !pokemon.isNull;
      });
    };

    Team.prototype.sync = function(method) {
      switch (method) {
        case 'create':
        case 'patch':
        case 'update':
          this.set('saving', true, {
            silent: true
          });
          this.trigger('remoteSync', this);
          return PokeBattle.primus.send('saveTeam', this.toJSON(), (function(_this) {
            return function(id) {
              _this.set('id', id);
              _this.set('saving', false, {
                silent: true
              });
              return _this.trigger('remoteSync', _this);
            };
          })(this));
        case 'delete':
          if (this.id) {
            return PokeBattle.primus.send('destroyTeam', this.id);
          }
      }
    };

    Team.prototype.getRandomOrder = function() {
      var order;
      order = this.get('randomorder');
      if (typeof order === 'undefined') {
        this.setRandomOrder();
        order = this.get('randomorder');
        return order;
      } else {
        order = this.get('randomorder');
        return order;
      }
    };

    Team.prototype.setRandomOrder = function() {
      var team, teamshuffled;
      team = this.get('pokemon').toJSON();
      teamshuffled = _.shuffle(team);
      return this.set('randomorder', teamshuffled);
    };

    return Team;

  })(Backbone.AssociatedModel);

}).call(this);

(function() {
  var Teams,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  Teams = (function(_super) {
    __extends(Teams, _super);

    function Teams() {
      return Teams.__super__.constructor.apply(this, arguments);
    }

    Teams.prototype.model = Team;

    return Teams;

  })(Backbone.Collection);

  this.Battle = (function(_super) {
    __extends(Battle, _super);

    function Battle() {
      this.notify = __bind(this.notify, this);
      this.forfeit = __bind(this.forfeit, this);
      this.isPlaying = __bind(this.isPlaying, this);
      this.getPokemon = __bind(this.getPokemon, this);
      this.getOpponentTeam = __bind(this.getOpponentTeam, this);
      this.getTeam = __bind(this.getTeam, this);
      this["switch"] = __bind(this["switch"], this);
      this.arrangeTeam = __bind(this.arrangeTeam, this);
      this.makeCancel = __bind(this.makeCancel, this);
      this.makeSwitch = __bind(this.makeSwitch, this);
      this.makeMove = __bind(this.makeMove, this);
      this.receiveTeam = __bind(this.receiveTeam, this);
      this.receiveTeams = __bind(this.receiveTeams, this);
      this.initialize = __bind(this.initialize, this);
      return Battle.__super__.constructor.apply(this, arguments);
    }

    Battle.prototype.relations = [
      {
        type: Backbone.Many,
        key: 'teams',
        relatedModel: Team,
        collectionType: Teams
      }
    ];

    Battle.prototype.defaults = {
      spectating: true,
      finished: false
    };

    _.extend(Battle.prototype, PokeBattle.mixins.BattleProtocolParser);

    Battle.prototype.initialize = function(attributes) {
      var allformats, spectators;
      this.updateQueue = [];
      this.numActive = attributes.numActive, spectators = attributes.spectators;
      if (!!spectators) {
        this.spectators = new UserList(spectators);
      }
      allformats = window.PokeBattle.conditions.Formats();
      this.set('generation', allformats[this.get('format')].generation);
      this.set('notifications', 0);
      this.set('turn', 0);
      this.set('teams', [
        {
          hidden: true
        }, {
          hidden: true
        }
      ]);
      this.set('spectating', !this.has('index'));
      if (!this.has('index')) {
        return this.set('index', Math.floor(2 * Math.random()));
      }
    };

    Battle.prototype.receiveTeams = function(receivedTeams) {
      var i, receivedTeam, team, teams, _i, _len, _results;
      teams = this.get('teams');
      _results = [];
      for (i = _i = 0, _len = receivedTeams.length; _i < _len; i = ++_i) {
        receivedTeam = receivedTeams[i];
        receivedTeam.hidden = true;
        team = teams.at(i);
        if (team.get('hidden')) {
          _results.push(team.set(receivedTeam));
        } else {
          _results.push(void 0);
        }
      }
      return _results;
    };

    Battle.prototype.receiveTeam = function(team) {
      var teams;
      teams = this.get('teams');
      return teams.at(this.get('index')).unset('hidden', {
        silent: true
      }).set(team);
    };

    Battle.prototype.makeMove = function(moveName, forSlot, callback) {
      var options, pokemon;
      pokemon = this.getPokemon(this.get('index'), forSlot);
      options = {};
      if (pokemon.get('megaEvolve')) {
        options['megaEvolve'] = pokemon.get('megaEvolve');
      }
      return PokeBattle.primus.send('sendMove', this.id, moveName, forSlot, this.get('turn'), options, callback);
    };

    Battle.prototype.makeSwitch = function(toSlot, forSlot, callback) {
      return PokeBattle.primus.send('sendSwitch', this.id, toSlot, forSlot, this.get('turn'), callback);
    };

    Battle.prototype.makeCancel = function() {
      return PokeBattle.primus.send('sendCancelAction', this.id, this.get('turn'));
    };

    Battle.prototype.arrangeTeam = function(arrangement) {
      return PokeBattle.primus.send('arrangeTeam', this.id, arrangement);
    };

    Battle.prototype["switch"] = function(fromIndex, toIndex) {
      var you, _ref;
      you = this.getTeam().pokemon;
      return _ref = [you[toIndex], you[fromIndex]], you[fromIndex] = _ref[0], you[toIndex] = _ref[1], _ref;
    };

    Battle.prototype.getTeam = function(playerIndex) {
      if (playerIndex == null) {
        playerIndex = this.get('index');
      }
      return this.get("teams").at(playerIndex);
    };

    Battle.prototype.getOpponentTeam = function(playerIndex) {
      if (playerIndex == null) {
        playerIndex = this.get('index');
      }
      return this.get("teams").at(1 - playerIndex);
    };

    Battle.prototype.getPokemon = function(playerIndex, slot) {
      var team;
      if (slot == null) {
        slot = 0;
      }
      team = this.getTeam(playerIndex);
      return team.at(slot);
    };

    Battle.prototype.isPlaying = function() {
      return !this.get('finished') && !this.get('spectating');
    };

    Battle.prototype.forfeit = function() {
      return PokeBattle.primus.send('forfeit', this.id);
    };

    Battle.prototype.notify = function() {
      return this.set('notifications', this.get('notifications') + 1);
    };

    return Battle;

  })(Backbone.AssociatedModel);

}).call(this);

(function() {
  var MAX_LOG_LENGTH,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __slice = [].slice;

  MAX_LOG_LENGTH = 50;

  this.PrivateMessage = (function(_super) {
    __extends(PrivateMessage, _super);

    function PrivateMessage() {
      this.logKey = __bind(this.logKey, this);
      this.saveLog = __bind(this.saveLog, this);
      this.loadLog = __bind(this.loadLog, this);
      this.getLog = __bind(this.getLog, this);
      this.closeChallenge = __bind(this.closeChallenge, this);
      this.cancelChallenge = __bind(this.cancelChallenge, this);
      this.openChallenge = __bind(this.openChallenge, this);
      this.add = __bind(this.add, this);
      this.initialize = __bind(this.initialize, this);
      return PrivateMessage.__super__.constructor.apply(this, arguments);
    }

    PrivateMessage.prototype.initialize = function() {
      this.loadLog();
      return this.set('notifications', 0);
    };

    PrivateMessage.prototype.add = function(username, message, opts) {
      var log;
      if (opts == null) {
        opts = {};
      }
      if (username === this.id) {
        this.set('notifications', this.get('notifications') + 1);
      }
      this.trigger("receive", this, this.id, username, message, opts);
      log = this.get('log');
      log.push({
        username: username,
        message: message,
        opts: opts
      });
      if (log.length > (2 * MAX_LOG_LENGTH)) {
        log.splice(0, log.length - MAX_LOG_LENGTH);
      }
      return this.saveLog();
    };

    PrivateMessage.prototype.openChallenge = function() {
      var args;
      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      return this.trigger.apply(this, ["openChallenge"].concat(__slice.call(args)));
    };

    PrivateMessage.prototype.cancelChallenge = function() {
      var args;
      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      return this.trigger.apply(this, ["cancelChallenge"].concat(__slice.call(args)));
    };

    PrivateMessage.prototype.closeChallenge = function() {
      var args;
      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      return this.trigger.apply(this, ["closeChallenge"].concat(__slice.call(args)));
    };

    PrivateMessage.prototype.getLog = function() {
      var log;
      log = this.get('log');
      if (log.length > 50) {
        log.splice(0, log.length - 50);
      }
      return log;
    };

    PrivateMessage.prototype.loadLog = function() {
      var log;
      try {
        log = JSON.parse(window.localStorage.getItem(this.logKey())) || [];
        return this.set('log', log);
      } catch (_error) {
        return this.set('log', []);
      }
    };

    PrivateMessage.prototype.saveLog = function() {
      try {
        return window.localStorage.setItem(this.logKey(), JSON.stringify(this.getLog()));
      } catch (_error) {}
    };

    PrivateMessage.prototype.logKey = function() {
      var key;
      key = [this.id, PokeBattle.username];
      key.sort();
      return key.join(':');
    };

    return PrivateMessage;

  })(Backbone.Model);

}).call(this);

(function() {
  var __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __slice = [].slice;

  this.Room = (function(_super) {
    var eventName, _fn, _i, _len, _ref;

    __extends(Room, _super);

    function Room() {
      return Room.__super__.constructor.apply(this, arguments);
    }

    Room.prototype.relations = [
      {
        type: Backbone.Many,
        key: 'users',
        relatedModel: 'User',
        collectionType: 'UserList'
      }
    ];

    Room.prototype.EVENTS = "userMessage rawMessage announce clear setTopic".split(/\s+/);

    _ref = Room.prototype.EVENTS;
    _fn = function(eventName) {
      return Room.prototype[eventName] = function() {
        var args;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        return this.trigger.apply(this, [eventName].concat(__slice.call(args)));
      };
    };
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      eventName = _ref[_i];
      _fn(eventName);
    }

    Room.prototype.sendChat = function(message) {
      if (!((message != null ? message.replace(/\s+$/).length : void 0) > 0)) {
        return false;
      }
      if (!PokeBattle.commands.execute(this, message)) {
        PokeBattle.primus.send('sendChat', this.id, message);
      }
      return true;
    };

    return Room;

  })(Backbone.AssociatedModel);

}).call(this);

(function() {
  var AuthorityMap,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  AuthorityMap = {
    "1": "",
    "2": "+",
    "3": "%",
    "4": "@",
    "5": "~"
  };

  this.User = (function(_super) {
    __extends(User, _super);

    function User() {
      this.isAlt = __bind(this.isAlt, this);
      this.getDisplayName = __bind(this.getDisplayName, this);
      this.initialize = __bind(this.initialize, this);
      return User.__super__.constructor.apply(this, arguments);
    }

    User.prototype.initialize = function(attributes) {};

    User.prototype.getDisplayName = function() {
      var authorityString, _ref;
      authorityString = (_ref = AuthorityMap[this.get('authority')]) != null ? _ref : "";
      return "" + authorityString + (this.get('id'));
    };

    User.prototype.isAlt = function() {
      return this.get('isAlt');
    };

    return User;

  })(Backbone.Model);

}).call(this);

(function() {
  var __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  this.BattleCollection = (function(_super) {
    __extends(BattleCollection, _super);

    function BattleCollection() {
      return BattleCollection.__super__.constructor.apply(this, arguments);
    }

    BattleCollection.prototype.model = Battle;

    BattleCollection.prototype.isPlaying = function() {
      return this.find(function(battle) {
        return battle.isPlaying();
      }) != null;
    };

    BattleCollection.prototype.playingBattles = function() {
      return this.filter(function(battle) {
        return battle.isPlaying();
      });
    };

    return BattleCollection;

  })(Backbone.Collection);

}).call(this);

(function() {
  var __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  this.PrivateMessages = (function(_super) {
    __extends(PrivateMessages, _super);

    function PrivateMessages() {
      return PrivateMessages.__super__.constructor.apply(this, arguments);
    }

    PrivateMessages.prototype.model = PrivateMessage;

    return PrivateMessages;

  })(Backbone.Collection);

}).call(this);

(function() {
  var __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __slice = [].slice;

  this.Rooms = (function(_super) {
    var eventName, _fn, _i, _len, _ref;

    __extends(Rooms, _super);

    function Rooms() {
      return Rooms.__super__.constructor.apply(this, arguments);
    }

    Rooms.prototype.model = Room;

    _ref = Room.prototype.EVENTS;
    _fn = function(eventName) {
      return Rooms.prototype[eventName] = function() {
        var args;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        return this.each(function(room) {
          return room[eventName].apply(room, args);
        });
      };
    };
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      eventName = _ref[_i];
      _fn(eventName);
    }

    return Rooms;

  })(Backbone.Collection);

}).call(this);

(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  this.UserList = (function(_super) {
    __extends(UserList, _super);

    function UserList() {
      this.initialize = __bind(this.initialize, this);
      this.comparator = __bind(this.comparator, this);
      return UserList.__super__.constructor.apply(this, arguments);
    }

    UserList.prototype.model = User;

    UserList.prototype.comparator = function(a, b) {
      var aAuthority, aName, bAuthority, bName;
      aAuthority = a.get('authority');
      bAuthority = b.get('authority');
      aName = ("" + a.id).toLowerCase();
      bName = ("" + b.id).toLowerCase();
      if (aAuthority < bAuthority) {
        return 1;
      } else if (aAuthority > bAuthority) {
        return -1;
      } else if (aName < bName) {
        return -1;
      } else if (aName > bName) {
        return 1;
      } else {
        return 0;
      }
    };

    UserList.prototype.initialize = function() {};

    return UserList;

  })(Backbone.Collection);

}).call(this);

(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
    __slice = [].slice;

  this.BattleView = (function(_super) {
    __extends(BattleView, _super);

    function BattleView() {
      this.setVisibleTeam = __bind(this.setVisibleTeam, this);
      this.pokemonHtml = __bind(this.pokemonHtml, this);
      this.remove = __bind(this.remove, this);
      this.getPokemonPosition = __bind(this.getPokemonPosition, this);
      this.addPokemonImage = __bind(this.addPokemonImage, this);
      this.preloadImages = __bind(this.preloadImages, this);
      this.afterAction = __bind(this.afterAction, this);
      this.afterSelection = __bind(this.afterSelection, this);
      this.megaEvolve = __bind(this.megaEvolve, this);
      this.cancelAction = __bind(this.cancelAction, this);
      this.switchPokemon = __bind(this.switchPokemon, this);
      this.makeMove = __bind(this.makeMove, this);
      this.continueTurn = __bind(this.continueTurn, this);
      this.beginTurn = __bind(this.beginTurn, this);
      this.addSummary = __bind(this.addSummary, this);
      this.addLog = __bind(this.addLog, this);
      this.isIllusioned = __bind(this.isIllusioned, this);
      this.addMoveMessage = __bind(this.addMoveMessage, this);
      this.disableButtons = __bind(this.disableButtons, this);
      this.enableButtons = __bind(this.enableButtons, this);
      this.resetPopovers = __bind(this.resetPopovers, this);
      this.faint = __bind(this.faint, this);
      this.isFront = __bind(this.isFront, this);
      this.$projectile = __bind(this.$projectile, this);
      this.$sprite = __bind(this.$sprite, this);
      this.$spriteContainer = __bind(this.$spriteContainer, this);
      this.$pokemon = __bind(this.$pokemon, this);
      this.changeBattleSpeed = __bind(this.changeBattleSpeed, this);
      this.returnToLobby = __bind(this.returnToLobby, this);
      this.saveLog = __bind(this.saveLog, this);
      this.saveReplay = __bind(this.saveReplay, this);
      this.shouldRenderEnd = __bind(this.shouldRenderEnd, this);
      this.handleRemoval = __bind(this.handleRemoval, this);
      this.handleEnd = __bind(this.handleEnd, this);
      this.announceWin = __bind(this.announceWin, this);
      this.announceExpiration = __bind(this.announceExpiration, this);
      this.announceTimer = __bind(this.announceTimer, this);
      this.announceForfeit = __bind(this.announceForfeit, this);
      this.announceWinner = __bind(this.announceWinner, this);
      this.$playerInfo = __bind(this.$playerInfo, this);
      this.resumeTimer = __bind(this.resumeTimer, this);
      this.pauseTimer = __bind(this.pauseTimer, this);
      this.renderTimer = __bind(this.renderTimer, this);
      this.countdownTimers = __bind(this.countdownTimers, this);
      this.renderTimers = __bind(this.renderTimers, this);
      this.updateTimers = __bind(this.updateTimers, this);
      this.unattachBattle = __bind(this.unattachBattle, this);
      this.unattachTeam = __bind(this.unattachTeam, this);
      this.addPokemonEffect = __bind(this.addPokemonEffect, this);
      this.mapStatusForDisplay = __bind(this.mapStatusForDisplay, this);
      this.showSpinner = __bind(this.showSpinner, this);
      this.handleStatus = __bind(this.handleStatus, this);
      this.handlePercent = __bind(this.handlePercent, this);
      this.resetBoosts = __bind(this.resetBoosts, this);
      this.setBoosts = __bind(this.setBoosts, this);
      this.unattachPokemon = __bind(this.unattachPokemon, this);
      this.boost = __bind(this.boost, this);
      this.unattachScreen = __bind(this.unattachScreen, this);
      this.attachScreen = __bind(this.attachScreen, this);
      this.attachBattle = __bind(this.attachBattle, this);
      this.attachTeam = __bind(this.attachTeam, this);
      this.attachPokemon = __bind(this.attachPokemon, this);
      this.changeWeather = __bind(this.changeWeather, this);
      this.changeName = __bind(this.changeName, this);
      this.changeSprite = __bind(this.changeSprite, this);
      this.activateAbility = __bind(this.activateAbility, this);
      this.getCannedText = __bind(this.getCannedText, this);
      this.actOnCannedText = __bind(this.actOnCannedText, this);
      this.parseCannedText = __bind(this.parseCannedText, this);
      this.cannedText = __bind(this.cannedText, this);
      this.moveSuccess = __bind(this.moveSuccess, this);
      this.logMove = __bind(this.logMove, this);
      this.removePokeball = __bind(this.removePokeball, this);
      this.makePokeball = __bind(this.makePokeball, this);
      this.switchOut = __bind(this.switchOut, this);
      this.switchIn = __bind(this.switchIn, this);
      this.floatText = __bind(this.floatText, this);
      this.floatPercent = __bind(this.floatPercent, this);
      this.removeTeamPreview = __bind(this.removeTeamPreview, this);
      this.submitTeamPreview = __bind(this.submitTeamPreview, this);
      this.togglePokemonOrSwitch = __bind(this.togglePokemonOrSwitch, this);
      this.renderTeamPreview = __bind(this.renderTeamPreview, this);
      this.pokemonPopover = __bind(this.pokemonPopover, this);
      this.movePopover = __bind(this.movePopover, this);
      this.renderUserInfo = __bind(this.renderUserInfo, this);
      this.renderWaiting = __bind(this.renderWaiting, this);
      this.renderActions = __bind(this.renderActions, this);
      this.renderChat = __bind(this.renderChat, this);
      this.renderControls = __bind(this.renderControls, this);
      this.renderPokemon = __bind(this.renderPokemon, this);
      this.renderBattle = __bind(this.renderBattle, this);
      this.render = __bind(this.render, this);
      this.initialize = __bind(this.initialize, this);
      return BattleView.__super__.constructor.apply(this, arguments);
    }

    BattleView.prototype.battle_template = JST['battle'];

    BattleView.prototype.user_info_template = JST['battle_user_info'];

    BattleView.prototype.action_template = JST['battle_actions'];

    BattleView.prototype.team_preview_template = JST['battle_team_preview'];

    BattleView.prototype.battle_end_template = JST['battle_end'];

    BattleView.prototype.battle_controls_template = JST['battle_controls'];

    BattleView.prototype.SPEEDS = {
      Instant: 0,
      Fast: 1,
      Medium: 1.5,
      Slow: 2
    };

    BattleView.prototype.events = {
      'click .move': 'makeMove',
      'click .switch': 'switchPokemon',
      'click .mega-evolve': 'megaEvolve',
      'click .cancel': 'cancelAction',
      'click .save-replay': 'saveReplay',
      'click .save-log': 'saveLog',
      'click .return-to-lobby': 'returnToLobby',
      'click .arrange_pokemon': 'togglePokemonOrSwitch',
      'click .submit_arrangement': 'submitTeamPreview',
      'change .battle-speed': 'changeBattleSpeed'
    };

    BattleView.prototype.initialize = function(options) {
      var _ref;
      this.chatView = null;
      this.lastMove = null;
      this.skip = null;
      this.room = (_ref = PokeBattle.rooms) != null ? _ref.add({
        id: this.model.id,
        users: []
      }) : void 0;
      try {
        this.speed = Number(window.localStorage.getItem('battle_speed'));
      } catch (_error) {

      }
      this.speed || (this.speed = 1);
      this.listenTo(this.model, 'change:teams[*].pokemon[*].status', this.handleStatus);
      this.listenTo(this.model, 'change:teams[*].pokemon[*].percent', this.handlePercent);
      this.listenTo(this.model, 'change:finished', this.handleEnd);
      if (this.model.collection) {
        this.listenTo(this.model.collection, 'remove', this.handleRemoval);
      }
      this.battleStartTime = $.now();
      this.timers = [];
      this.timerUpdatedAt = [];
      this.timerFrozenAt = [];
      this.timerIterations = 0;
      this.countdownTimers();
      return this.render();
    };

    BattleView.prototype.render = function() {
      this.renderChat();
      return this;
    };

    BattleView.prototype.renderBattle = function() {
      var locals;
      locals = {
        yourTeam: this.model.getTeam(),
        opponentTeam: this.model.getOpponentTeam(),
        numActive: this.model.numActive,
        yourIndex: this.model.get('index'),
        window: window
      };
      this.$('.battle_pane').html(this.battle_template(locals));
      this.renderPokemon();
      this.renderControls();
      return this;
    };

    BattleView.prototype.renderPokemon = function($images, callback) {
      var battle, self;
      $images || ($images = this.$('.preload'));
      battle = this.model;
      self = this;
      $images.each(function() {
        var $pokemon, $this, forme, front, gen, id, player, scale, shiny, slot, species, url, _ref;
        $this = $(this);
        $pokemon = $this.closest('.pokemon');
        _ref = [$pokemon.data('team'), $pokemon.data('slot')], player = _ref[0], slot = _ref[1];
        front = $pokemon.hasClass('top');
        species = $this.data('species');
        forme = $this.data('forme');
        shiny = $this.data('shiny');
        gen = battle.get('generation').toUpperCase();
        id = window.Generations[gen].SpeciesData[species].id;
        url = PokemonSprite(id, forme, {
          front: front,
          shiny: shiny
        });
        scale = front ? 0.7 : 0.9;
        return self.addPokemonImage($this, url, {
          scale: scale,
          callback: function($image) {
            var height, image, width, x, y, _ref1;
            image = $image[0];
            width = image.width, height = image.height;
            _ref1 = self.getPokemonPosition(player, slot), x = _ref1[0], y = _ref1[1];
            x -= width >> 1;
            y -= height >> 1;
            if (!front) {
              y += 30;
            }
            $image.css({
              top: y,
              left: x
            }).show();
            return typeof callback === "function" ? callback($image) : void 0;
          }
        });
      });
      return this;
    };

    BattleView.prototype.renderControls = function() {
      var html;
      html = this.battle_controls_template({
        speeds: this.SPEEDS,
        currentSpeed: this.speed
      });
      this.$el.find('.battle-controls').html(html);
      return this;
    };

    BattleView.prototype.renderChat = function() {
      this.chatView = new ChatView({
        el: this.$('.chat'),
        model: this.room,
        noisy: true
      }).render();
      return this;
    };

    BattleView.prototype.renderActions = function(validActions) {
      var $actions, $button, locals, pokemon, _ref;
      if (validActions == null) {
        validActions = [];
      }
      locals = {
        yourTeam: this.model.getTeam(),
        validActions: validActions[0] || {},
        window: window
      };
      $actions = this.$('.battle_actions');
      $actions.html(this.action_template(locals));
      pokemon = this.model.getPokemon(this.model.get('index'), 0);
      if (((_ref = pokemon.getItem()) != null ? _ref.type : void 0) === 'megastone') {
        $button = $actions.find('.mega-evolve');
        $button.removeClass("hidden");
        if (!pokemon.canMegaEvolve()) {
          $button.addClass('disabled');
        }
      }
      $actions.find('.move.button').each((function(_this) {
        return function(i, el) {
          var $this, gen, moveData, moveName, _ref1;
          $this = $(el);
          moveName = $this.data('move-id');
          gen = _this.model.get('generation').toUpperCase();
          moveData = (_ref1 = window.Generations[gen]) != null ? _ref1.MoveData[moveName] : void 0;
          return _this.movePopover($this, moveName, moveData);
        };
      })(this));
      $actions.find('.switch.button').each((function(_this) {
        return function(i, el) {
          var $this, slot;
          $this = $(el);
          slot = $this.data('slot');
          pokemon = _this.model.getPokemon(_this.model.get('index'), slot);
          return _this.pokemonPopover($this, pokemon);
        };
      })(this));
      return this;
    };

    BattleView.prototype.renderWaiting = function() {
      var $actions;
      $actions = this.$('.battle_actions');
      $actions.find('.move.button').popover('destroy');
      return $actions.html("<div class=\"well well-battle-actions\">\n  Waiting for opponent...\n  <a class=\"cancel\">Cancel</a>\n</div>");
    };

    BattleView.prototype.renderUserInfo = function() {
      var $userInfo, locals;
      locals = {
        yourTeam: this.model.getTeam(),
        opponentTeam: this.model.getOpponentTeam(),
        numActive: this.model.numActive,
        yourIndex: this.model.get('index'),
        window: window
      };
      $userInfo = this.$('.battle_user_info');
      $userInfo.find('.pokemon_icon').popover('destroy');
      $userInfo.html(this.user_info_template(locals));
      $userInfo.find('.pokemon_icon').each((function(_this) {
        return function(i, el) {
          var $this, pokemon, slot, team;
          $this = $(el);
          team = $this.data('team');
          slot = $this.data('slot');
          return pokemon = _this.model.getPokemon(team, slot);
        };
      })(this));
      this.renderTimers();
      return this;
    };

    BattleView.prototype.movePopover = function($this, moveName, move) {
      var damage, damageFriendly, displayName, options, targetFriendly, type;
      type = move.type, damage = move.damage;
      damageFriendly = move.damage[0].toUpperCase() + move.damage.substr(1);
      targetFriendly = move.target[0].toUpperCase() + move.target.substr(1);
      displayName = [];
      displayName.push(moveName);
      displayName.push("<img src=\"" + (TypeSprite(type)) + "\" alt=\"" + type + "\"/>\n<img src=\"" + (CategorySprite(move.damage)) + "\" alt=\"" + damageFriendly + "\"/>\n<img src=\"" + (TargetSprite(move)) + "\" alt=\"" + targetFriendly + "\"/>");
      options = {
        title: displayName.join('<br>'),
        html: true,
        content: JST['move_hover_info']({
          window: window,
          move: move
        }),
        trigger: 'hover',
        animation: false,
        placement: 'top',
        container: 'body'
      };
      return $this.popover(options);
    };

    BattleView.prototype.pokemonPopover = function($this, pokemon) {
      var displayName, options, type, _i, _len, _ref;
      if (this.isIllusioned(pokemon)) {
        pokemon = pokemon.getTeam().attributes.pokemon.at(pokemon.getTeam().attributes.pokemon.length - 1);
      }
      displayName = pokemon.get('species');
      if (pokemon.has('item')) {
        displayName += " @ " + (pokemon.get('item'));
      }
      displayName += "<br>";
      _ref = pokemon.getForme().types;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        type = _ref[_i];
        displayName += "<img src=\"" + (TypeSprite(type)) + "\" alt=\"" + type + "\"/>";
      }
      options = {
        title: displayName,
        html: true,
        content: JST['battle_hover_info']({
          window: window,
          pokemon: pokemon
        }),
        trigger: 'hover',
        animation: false,
        container: 'body'
      };
      return $this.popover(options);
    };

    BattleView.prototype.renderTeamPreview = function() {
      var locals;
      locals = {
        battle: this.model,
        window: window
      };
      return this.$('.battle_container').append(this.team_preview_template(locals));
    };

    BattleView.prototype.togglePokemonOrSwitch = function(e) {
      var $activePokemon, $currentTarget;
      $currentTarget = $(e.currentTarget);
      $activePokemon = this.$('.arrange_pokemon.active');
      if ($currentTarget.is('.active')) {
        return $activePokemon.removeClass('active');
      } else if ($activePokemon.length > 0) {
        $activePokemon.removeClass('active');
        return this.swapElements($currentTarget.get(0), $activePokemon.get(0));
      } else {
        return $currentTarget.addClass('active');
      }
    };

    BattleView.prototype.swapElements = function(element1, element2) {
      var next1, next2, parent1, parent2, _ref, _ref1;
      _ref = [element1.parentNode, element1.nextSibling], parent1 = _ref[0], next1 = _ref[1];
      _ref1 = [element2.parentNode, element2.nextSibling], parent2 = _ref1[0], next2 = _ref1[1];
      parent1.insertBefore(element2, next1);
      return parent2.insertBefore(element1, next2);
    };

    BattleView.prototype.submitTeamPreview = function(e) {
      var $currentTarget, $teamPreview, element, indices;
      $currentTarget = $(e.currentTarget);
      if ($currentTarget.hasClass('disabled')) {
        return;
      }
      $currentTarget.addClass('disabled');
      $teamPreview = this.$('.battle_teams');
      indices = (function() {
        var _i, _len, _ref, _results;
        _ref = this.$('.arrange_team .pokemon_icon');
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          element = _ref[_i];
          _results.push($(element).data('index'));
        }
        return _results;
      }).call(this);
      this.model.arrangeTeam(indices);
      return $teamPreview.transition({
        opacity: 0
      }, 250, (function(_this) {
        return function() {
          return _this.removeTeamPreview();
        };
      })(this));
    };

    BattleView.prototype.removeTeamPreview = function() {
      var $teamPreview;
      $teamPreview = this.$('.battle_teams');
      return $teamPreview.remove();
    };

    BattleView.prototype.floatPercent = function(player, slot, percent) {
      var kind, percentText;
      if (this.skip != null) {
        return;
      }
      kind = (percent >= 0 ? "" : "red");
      percentText = "" + percent;
      if (percent >= 0) {
        percentText = "+" + percentText;
      }
      percentText += "%";
      return this.floatText(player, slot, percentText, kind);
    };

    BattleView.prototype.floatText = function(player, slot, text, kind) {
      var $sprite, $text, x, y, _ref;
      if (kind == null) {
        kind = "";
      }
      if (this.skip != null) {
        return;
      }
      $sprite = this.$sprite(player, slot);
      _ref = this.getPokemonPosition(player, slot), x = _ref[0], y = _ref[1];
      $text = $('<span/>').addClass("percentage " + kind).text(text);
      $text.hide().appendTo(this.$('.battle_pane'));
      x -= $text.width() / 2;
      y -= 20;
      $text.css({
        position: 'absolute',
        top: y,
        left: x
      }).show();
      if (kind === 'red') {
        $text.transition({
          top: "+=30"
        }, 1000, 'easeOutCubic');
        $text.delay(1000);
        return $text.transition({
          opacity: 0
        }, 1000, function() {
          return $text.remove();
        });
      } else {
        $text.transition({
          top: "-=30"
        }, 1000, 'easeOutCubic');
        $text.delay(1000);
        return $text.transition({
          opacity: 0
        }, 1000, function() {
          return $text.remove();
        });
      }
    };

    BattleView.prototype.switchIn = function(player, slot, fromSlot, done) {
      var $newPokemon, $newSprite, $oldPokemon, $pokeball, pokemon, releasePokemon, x, y, _ref;
      $oldPokemon = this.$pokemon(player, slot);
      $newPokemon = this.$pokemon(player, fromSlot);
      $newSprite = this.$sprite(player, fromSlot);
      pokemon = this.model.getPokemon(player, slot);
      this.renderUserInfo();
      $oldPokemon.attr('data-slot', fromSlot);
      $newPokemon.attr('data-slot', slot);
      $newPokemon.removeClass('hidden');
      this.pokemonPopover($newSprite, pokemon);
      pokemon.set('beeninbattle', true);
      this.cannedText('SENT_OUT', player, player, slot);
      if (this.skip != null) {
        $oldPokemon.css({
          opacity: 0
        });
        $newPokemon.css({
          opacity: 1
        });
        done();
        return;
      }
      _ref = this.getPokemonPosition(player, slot), x = _ref[0], y = _ref[1];
      $pokeball = this.makePokeball(x, y);
      $pokeball.css({
        opacity: 0
      });
      $pokeball.appendTo(this.$(".battle_pane"));
      $oldPokemon.css({
        opacity: 0
      });
      $newPokemon.css({
        opacity: 0
      });
      $pokeball.css({
        opacity: 1
      });
      releasePokemon = (function(_this) {
        return function() {
          $pokeball.css({
            opacity: 0
          });
          $newSprite.transition({
            y: -15,
            scale: .1
          }, 0).transition({
            scale: 1
          }, 250 * _this.speed).transition({
            y: 0
          }, 250 * _this.speed, 'out', function() {
            return _this.removePokeball($pokeball);
          });
          setTimeout(done, 500 * _this.speed);
          return $newPokemon.transition({
            opacity: 1
          });
        };
      })(this);
      return setTimeout(releasePokemon, 250 * this.speed);
    };

    BattleView.prototype.switchOut = function(player, slot, done) {
      var $pokemon, $sprite, height, width;
      $pokemon = this.$pokemon(player, slot);
      $sprite = this.$sprite(player, slot);
      this.cannedText('WITHDREW', player, player, slot);
      if (this.skip != null) {
        $pokemon.addClass('hidden');
        $sprite.popover('destroy');
        done();
        return;
      }
      width = $sprite.width();
      height = $sprite.height();
      $sprite.transition({
        scale: 0.1,
        x: width >> 1,
        y: height
      }, 150 * this.speed);
      $pokemon.transition({
        opacity: 0
      }, 250 * this.speed, function() {
        $pokemon.addClass('hidden').css({
          opacity: 1
        });
        $sprite.popover('destroy');
        return $sprite.transition({
          scale: 1,
          x: 0,
          y: 0
        }, 0);
      });
      return setTimeout(done, 250 * this.speed);
    };

    BattleView.prototype.makePokeball = function(x, y) {
      var $pokeball, func, id, size;
      $pokeball = $("<div class=\"pokeball\"/>");
      $pokeball.css({
        top: y,
        left: x
      });
      size = 22;
      $pokeball.width(size).height(size);
      func = function() {
        $pokeball.css({
          backgroundPositionY: -10 - func.counter * 40
        });
        return func.counter = (func.counter + 1) % 8;
      };
      func.counter = 1;
      id = setInterval(func, 40);
      $pokeball.data('animation-id', id);
      return $pokeball;
    };

    BattleView.prototype.removePokeball = function($pokeball) {
      var id;
      id = $pokeball.data('animation-id');
      clearTimeout(id);
      return $pokeball.remove();
    };

    BattleView.prototype.logMove = function(player, slot, moveName, done) {
      var owner, pokemon;
      owner = this.model.getTeam(player).escape('owner');
      pokemon = this.model.getPokemon(player, slot);
      this.addMoveMessage(owner, pokemon, moveName);
      this.lastMove = moveName;
      return done();
    };

    BattleView.prototype.moveSuccess = function(player, slot, targetSlots, moveName, done) {
      var $attacker, $defender, $projectile, ax, ay, dx, dy, front, gen, moveData, scale, speed, targetPlayer, targetSlot, transX, transY, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
      if (this.skip != null) {
        return done();
      }
      gen = this.model.get('generation').toUpperCase();
      moveData = (_ref = window.Generations[gen]) != null ? _ref.MoveData[moveName] : void 0;
      if (!moveData) {
        console.error("Could not display animation for " + moveName + " as it does not exist in " + gen + ".");
        done();
        return;
      }
      _ref1 = targetSlots[0], targetPlayer = _ref1[0], targetSlot = _ref1[1];
      $attacker = this.$sprite(player, slot);
      $defender = this.$sprite(targetPlayer, targetSlot);
      _ref2 = this.getPokemonPosition(player, slot), ax = _ref2[0], ay = _ref2[1];
      _ref3 = this.getPokemonPosition(targetPlayer, targetSlot), dx = _ref3[0], dy = _ref3[1];
      front = this.isFront(player);
      scale = (front ? 1.3 : 1 / 1.3);
      if (moveName === 'Earthquake') {
        speed = this.speed;
        $attacker.add($defender).each(function(index) {
          return $(this).transition({
            x: -75
          }, 62.5 * speed, 'easeInOutCubic').transition({
            x: 75
          }, 125 * speed, 'easeInOutCubic').transition({
            x: -30
          }, 125 * speed, 'easeInOutCubic').transition({
            x: 30
          }, 125 * speed, 'easeInOutCubic').transition({
            x: 0
          }, 62.5 * speed, 'easeInOutCubic');
        });
        return setTimeout(done, 500 * this.speed);
      } else if (__indexOf.call(moveData.flags, 'contact') >= 0) {
        $attacker.transition({
          x: dx - ax,
          y: dy - ay,
          scale: scale
        }, 250 * this.speed, 'in').transition({
          x: 0,
          y: 0,
          scale: 1
        }, 250 * this.speed, 'out');
        $defender.delay(400 * this.speed).transition({
          x: (front ? -16 : 8)
        }, 50 * this.speed, 'easeOutCubic').transition({
          x: 0
        }, 50 * this.speed, 'easeInOutCubic');
        return setTimeout(done, 500 * this.speed);
      } else if (moveData['power'] > 0) {
        $projectile = this.$projectile(player, slot, moveData);
        _ref4 = [dx - ax, dy - ay], transX = _ref4[0], transY = _ref4[1];
        $projectile.transition({
          x: transX / 2,
          y: transY / 2,
          scale: (scale + 1) / 2
        }, 200 * this.speed, 'easeOutCubic').transition({
          x: transX,
          y: transY,
          scale: scale
        }, 200 * this.speed, 'easeOutCubic').transition({
          opacity: 0
        }, 100 * this.speed, function() {
          return $projectile.remove();
        });
        $defender.delay(400 * this.speed).transition({
          x: -4
        }, 0, 'linear').delay(50 * this.speed).transition({
          x: 4
        }, 0, 'linear').delay(50 * this.speed).transition({
          x: 0
        }, 0, 'linear');
        return setTimeout(done, 500 * this.speed);
      } else if (player !== targetPlayer || slot !== targetSlot) {
        $projectile = this.$projectile(player, slot, moveData);
        _ref5 = [dx - ax, dy - ay], transX = _ref5[0], transY = _ref5[1];
        $projectile.transition({
          x: transX * 2 / 3,
          y: transY / 3
        }, 150 * this.speed, 'easeInOutSine').transition({
          x: transX / 3,
          y: transY * 2 / 3
        }, 100 * this.speed, 'easeInOutSine').transition({
          x: transX,
          y: transY
        }, 150 * this.speed, 'easeInOutSine').transition({
          opacity: 0
        }, 100 * this.speed, 'easeInOutSine', function() {
          return $projectile.remove();
        });
        return setTimeout(done, 500 * this.speed);
      } else {
        $attacker = this.$sprite(player, slot);
        $attacker.transition({
          x: -16
        }, 125 * this.speed, 'easeInOutSine').transition({
          x: 16
        }, 250 * this.speed, 'easeInOutSine').transition({
          x: 0
        }, 125 * this.speed, 'easeInOutSine');
        return setTimeout(done, 500 * this.speed);
      }
    };

    BattleView.prototype.cannedText = function() {
      var args, cannedString;
      cannedString = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
      return this.parseCannedText(CannedText[cannedString], args, function() {});
    };

    BattleView.prototype.parseCannedText = function(cannedInteger, args, done) {
      var cannedText, cannedTextName;
      cannedTextName = CannedMapReverse[cannedInteger];
      cannedText = this.getCannedText(cannedTextName, args);
      this.addLog(cannedText);
      return this.actOnCannedText(cannedTextName, cannedText, done);
    };

    BattleView.prototype.actOnCannedText = function(cannedTextName, cannedText, done) {
      if (this.skip != null) {
        return done();
      }
      switch (cannedTextName) {
        case 'MOVE_MISS':
        case 'JUMP_KICK_MISS':
        case 'MOVE_FAIL':
        case 'IMMUNITY':
          this.addSummary(cannedText);
          return setTimeout(done, 500 * this.speed);
        case 'PARALYZE_CONTINUE':
        case 'FREEZE_CONTINUE':
        case 'SLEEP_CONTINUE':
        case 'SUN_END':
        case 'RAIN_END':
        case 'SAND_END':
        case 'HAIL_END':
        case 'SAND_CONTINUE':
        case 'HAIL_CONTINUE':
          this.addSummary(cannedText, {
            newline: true
          });
          return done();
        default:
          this.addSummary(cannedText);
          return done();
      }
    };

    BattleView.prototype.getCannedText = function(cannedTextName, args) {
      var cannedText, genIndex, generation, i, language, _i, _ref, _ref1;
      cannedText = 'Please refresh to see this text!';
      genIndex = ALL_GENERATIONS.indexOf(this.model.get('generation'));
      language = 'en';
      for (i = _i = genIndex; _i >= 0; i = _i += -1) {
        generation = ALL_GENERATIONS[i];
        if ((_ref = CannedMap[generation]) != null ? (_ref1 = _ref[language]) != null ? _ref1[cannedTextName] : void 0 : void 0) {
          cannedText = CannedMap[generation][language][cannedTextName];
          break;
        }
      }
      return cannedText.replace(/\$([a-z]+|\d+)/g, (function(_this) {
        return function(match, p1, index) {
          var player, pokemon, slot, text, _ref2;
          switch (p1) {
            case 'p':
              _ref2 = args.splice(0, 2), player = _ref2[0], slot = _ref2[1];
              pokemon = _this.model.getPokemon(player, slot);
              if (_this.isIllusioned(pokemon)) {
                pokemon = pokemon.getTeam().attributes.pokemon.at(pokemon.getTeam().attributes.pokemon.length - 1);
              }
              return pokemon.escape('name');
            case 't':
              player = args.splice(0, 1)[0];
              return _this.model.getTeam(player).escape('owner');
            case 'ts':
              player = args.splice(0, 1)[0];
              text = _this.isFront(player) ? "the opposing team" : "your team";
              if (index === 0) {
                text = "" + (text[0].toUpperCase()) + text.slice(1);
              }
              return text;
            default:
              text = args.splice(0, 1)[0];
              return text;
          }
        };
      })(this));
    };

    BattleView.prototype.activateAbility = function(player, slot, abilityName, done) {
      var $ability, isFront, pokemon;
      if (this.skip != null) {
        return done();
      }
      pokemon = this.model.getPokemon(player, slot);
      isFront = this.isFront(player);
      $ability = $('<div/>').addClass('ability_activation');
      $ability.html("" + (pokemon.escape('name')) + "'s <strong>" + abilityName + "</strong>");
      $ability.addClass((isFront ? 'front' : 'back'));
      $ability.width(1);
      $ability.appendTo(this.$('.battle_pane'));
      $ability.transition({
        opacity: 1,
        width: 150
      }, 100 * this.speed, 'easeInQuad').delay(3000).transition({
        opacity: 0
      }, 300 * this.speed, 'easeInQuad', function() {
        return $ability.remove();
      });
      return setTimeout(done, 500 * this.speed);
    };

    BattleView.prototype.changeSprite = function(player, slot, species, forme, done) {
      var $sprite, $spriteContainer;
      $spriteContainer = this.$spriteContainer(player, slot);
      $sprite = this.$sprite(player, slot);
      $spriteContainer.data('species', species);
      $spriteContainer.data('forme', forme);
      if (this.skip != null) {
        this.renderPokemon($spriteContainer, function() {
          $sprite.popover('destroy');
          return $sprite.remove();
        });
        done();
        return;
      }
      $sprite.fadeOut(200 * this.speed, (function(_this) {
        return function() {
          return _this.renderPokemon($spriteContainer, function($image) {
            $sprite.popover('destroy');
            $sprite.remove();
            return $image.hide().fadeIn(200 * this.speed);
          });
        };
      })(this));
      if (this.model.getPokemon(player, slot).isFainted()) {
        return done();
      } else {
        return setTimeout(done, 400 * this.speed);
      }
    };

    BattleView.prototype.changeName = function(player, slot, newName, done) {
      var nameBox;
      nameBox = this.$pokemon(player, slot).find('.pokemon-name');
      nameBox.html(newName);
      return done();
    };

    BattleView.prototype.changeWeather = function(newWeather, done) {
      var $drop, $hailstone, $overlays, $ray, $sand, $weather, dropLeft, dropTop, hailstoneLeft, hailstoneTop, height, i, left, millisecs, overlayHeight, overlayWidth, percentX, percentY, sandHeight, sandWidth, size, streams, top, width, x, y, _ref;
      $overlays = this.$('.battle_overlays');
      $overlays.find('.weather').transition({
        opacity: 0
      }, 500 * this.speed, function() {
        return $(this).remove();
      });
      _ref = [600, 300], overlayWidth = _ref[0], overlayHeight = _ref[1];
      $weather = (function() {
        var _i, _j, _k, _l, _len, _m, _n, _ref1, _ref2, _ref3, _ref4, _ref5;
        switch (newWeather) {
          case Weather.RAIN:
            $weather = $("<div/>").addClass("battle_overlay weather rain");
            for (i = _i = 0; _i < 100; i = ++_i) {
              dropLeft = _.random(-300, overlayWidth);
              dropTop = _.random(-2 * overlayHeight - 100, overlayHeight);
              $drop = $('<div class="drop"></div>');
              $drop.css({
                left: dropLeft,
                top: dropTop
              });
              $weather.append($drop);
            }
            $overlays.append($weather);
            return $weather;
          case Weather.SUN:
            $weather = $("<div/>").addClass("battle_overlay weather sun");
            for (i = _j = 0; _j < 10; i = ++_j) {
              millisecs = Math.floor(Math.random() * 3000) + 'ms';
              $ray = $('<div class="ray"></div>');
              $ray.css({
                left: Math.floor(Math.random() * overlayWidth)
              });
              $ray.css({
                '-webkit-animation-delay': millisecs,
                '-moz-animation-delay': millisecs,
                '-ms-animation-delay': millisecs,
                '-o-animation-delay': millisecs,
                'animation-delay': millisecs
              });
              $weather.append($ray);
            }
            $overlays.append($weather);
            return $weather;
          case Weather.SAND:
            $weather = $("<div/>").addClass("battle_overlay weather sand");
            _ref1 = [overlayWidth, overlayHeight], width = _ref1[0], height = _ref1[1];
            _ref2 = [600, 600], sandWidth = _ref2[0], sandHeight = _ref2[1];
            streams = [];
            for (x = _k = _ref3 = -(2 * width); sandWidth > 0 ? _k <= width : _k >= width; x = _k += sandWidth) {
              for (y = _l = _ref4 = -(2 * height); sandHeight > 0 ? _l < height : _l > height; y = _l += sandHeight) {
                percentX = Math.floor(100 * x / width) + "%";
                percentY = Math.floor(100 * y / height) + "%";
                streams.push([percentX, percentY]);
              }
            }
            for (_m = 0, _len = streams.length; _m < _len; _m++) {
              _ref5 = streams[_m], left = _ref5[0], top = _ref5[1];
              $sand = $('<div class="sand_overlay"/>');
              $sand.css({
                left: left,
                top: top
              });
              $weather.append($sand);
            }
            $overlays.append($weather);
            return $weather;
          case Weather.HAIL:
            $weather = $("<div/>").addClass("battle_overlay weather hail");
            for (i = _n = 0; _n < 100; i = ++_n) {
              hailstoneLeft = _.random(-300, overlayWidth);
              hailstoneTop = _.random(-2 * overlayHeight, overlayHeight);
              $hailstone = $('<div class="hailstone"></div>');
              size = Math.floor(Math.random() * 5) + 5;
              $hailstone.width(size);
              $hailstone.height(size);
              $hailstone.css({
                left: hailstoneLeft,
                top: hailstoneTop
              });
              $weather.append($hailstone);
            }
            $overlays.append($weather);
            return $weather;
          default:
            return $();
        }
      })();
      $weather.transition({
        opacity: 1
      }, 500 * this.speed);
      return done();
    };

    BattleView.prototype.attachPokemon = function(player, slot, attachment, done) {
      var $pokemon, $spriteContainer, pokemon, substituteUrl;
      pokemon = this.model.getPokemon(player, slot);
      $pokemon = this.$pokemon(player, slot);
      switch (attachment) {
        case 'SubstituteAttachment':
          $spriteContainer = this.$spriteContainer(player, slot);
          $spriteContainer.addClass('fade');
          substituteUrl = (this.isFront(player) ? "substitute" : "subback");
          substituteUrl = "../Sprites/battle/" + substituteUrl + ".gif";
          return this.addPokemonImage($pokemon, substituteUrl, {
            callback: (function(_this) {
              return function($image) {
                var height, width, x, y, yOffset, _ref;
                _ref = _this.getPokemonPosition(player, slot), x = _ref[0], y = _ref[1];
                $image.addClass('substitute');
                width = $image.width();
                height = $image.height();
                x -= width >> 1;
                y -= height >> 1;
                yOffset = 200;
                $image.css({
                  position: 'absolute',
                  left: x,
                  top: y
                });
                $image.show();
                if (_this.skip != null) {
                  return done();
                }
                setTimeout(function() {
                  return $image.transition({
                    y: -yOffset
                  }, 0).transition({
                    y: 0
                  }, 200 * this.speed, 'easeInQuad').transition({
                    y: -yOffset >> 3
                  }, 100 * this.speed, 'easeOutQuad').transition({
                    y: 0
                  }, 100 * this.speed, 'easeInQuad');
                }, 0);
                return setTimeout(done, 500 * _this.speed);
              };
            })(this)
          });
        case 'ConfusionAttachment':
          this.addPokemonEffect($pokemon, "confusion", "Confusion");
          this.addLog("" + (pokemon.escape('name')) + " became confused!");
          return done();
        case 'ProtectAttachment':
        case 'KingsShieldAttachment':
        case 'SpikyShieldAttachment':
          this.cannedText('PROTECT_CONTINUE', player, slot);
          return this.attachScreen(player, slot, 'pink', 0, done);
        case 'Air Balloon':
          this.addPokemonEffect($pokemon, "balloon", "Balloon");
          this.addLog("" + (pokemon.escape('name')) + " floats in the air with its Air Balloon!");
          return done();
        case 'Paralyze':
          pokemon.set('status', 'paralyze');
          return done();
        case 'Burn':
          pokemon.set('status', 'burn');
          return done();
        case 'Poison':
          pokemon.set('status', 'poison');
          return done();
        case 'Toxic':
          pokemon.set('status', 'toxic');
          return done();
        case 'Freeze':
          pokemon.set('status', 'freeze');
          return done();
        case 'Sleep':
          pokemon.set('status', 'sleep');
          return done();
        default:
          return done();
      }
    };

    BattleView.prototype.attachTeam = function(player, attachment, done) {
      var $battlePane, $div, isFront, newX, newY, oldX, oldY, previousLayers, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
      $battlePane = this.$('.battle_pane');
      isFront = this.isFront(player);
      switch (attachment) {
        case "StealthRockAttachment":
          $div = $("<div/>").addClass("field-" + player + " team-stealth-rock");
          if (isFront) {
            _ref = ["20%", "80%"], oldX = _ref[0], oldY = _ref[1];
            _ref1 = ["67%", "45%"], newX = _ref1[0], newY = _ref1[1];
          } else {
            _ref2 = ["80%", "20%"], oldX = _ref2[0], oldY = _ref2[1];
            _ref3 = ["34%", "81%"], newX = _ref3[0], newY = _ref3[1];
          }
          if (this.skip != null) {
            $div.css({
              top: newY,
              left: newX,
              opacity: .5
            });
            $battlePane.prepend($div);
            return done();
          } else {
            $div.css({
              top: oldY,
              left: oldX,
              opacity: 0
            });
            $div.transition({
              top: newY,
              left: newX,
              opacity: 1
            }, 500 * this.speed).delay(1000 * this.speed).transition({
              opacity: .5
            });
            $battlePane.prepend($div);
            return setTimeout(done, 500 * this.speed);
          }
          break;
        case "ToxicSpikesAttachment":
          $div = $("<div/>").addClass("field-" + player + " team-toxic-spikes");
          previousLayers = this.$(".field-" + player + ".team-toxic-spikes").length;
          if (isFront) {
            oldY = "80%";
            oldX = "20%";
            newY = (function() {
              switch (previousLayers) {
                case 0:
                  return "51%";
                case 1:
                  return "50%";
              }
            })();
            newX = (function() {
              switch (previousLayers) {
                case 0:
                  return "77%";
                case 1:
                  return "73%";
              }
            })();
          } else {
            oldY = "30%";
            oldX = "80%";
            newY = (function() {
              switch (previousLayers) {
                case 0:
                  return "87%";
                case 1:
                  return "86%";
              }
            })();
            newX = (function() {
              switch (previousLayers) {
                case 0:
                  return "23%";
                case 1:
                  return "27%";
              }
            })();
          }
          if (this.skip != null) {
            $div.css({
              top: newY,
              left: newX,
              opacity: .5
            });
            $battlePane.prepend($div);
            return done();
          } else {
            $div.css({
              top: oldY,
              left: oldX,
              opacity: 0
            });
            $div.transition({
              top: newY,
              left: newX,
              opacity: 1
            }, 500 * this.speed).delay(1000 * this.speed).transition({
              opacity: .5
            });
            $battlePane.prepend($div);
            return setTimeout(done, 500 * this.speed);
          }
          break;
        case "SpikesAttachment":
          $div = $("<div/>").addClass("field-" + player + " team-spikes");
          previousLayers = this.$(".field-" + player + ".team-spikes").length;
          if (isFront) {
            oldY = "80%";
            oldX = "20%";
            newY = (function() {
              switch (previousLayers) {
                case 0:
                  return "49%";
                case 1:
                  return "52%";
                case 2:
                  return "50%";
              }
            })();
            newX = (function() {
              switch (previousLayers) {
                case 0:
                  return "87%";
                case 1:
                  return "84%";
                case 2:
                  return "82%";
              }
            })();
          } else {
            oldY = "30%";
            oldX = "80%";
            newY = (function() {
              switch (previousLayers) {
                case 0:
                  return "85%";
                case 1:
                  return "88%";
                case 2:
                  return "86%";
              }
            })();
            newX = (function() {
              switch (previousLayers) {
                case 0:
                  return "13%";
                case 1:
                  return "16%";
                case 2:
                  return "18%";
              }
            })();
          }
          if (this.skip != null) {
            $div.css({
              top: newY,
              left: newX,
              opacity: .5
            });
            $battlePane.prepend($div);
            return done();
          } else {
            $div.css({
              top: oldY,
              left: oldX,
              opacity: 0
            });
            $div.transition({
              top: newY,
              left: newX,
              opacity: 1
            }, 500 * this.speed).delay(1000 * this.speed).transition({
              opacity: .5
            });
            $battlePane.prepend($div);
            return setTimeout(done, 500 * this.speed);
          }
          break;
        case "StickyWebAttachment":
          $div = $("<div/>").addClass("field-" + player + " team-sticky-web");
          if (isFront) {
            _ref4 = ["0%", "50%"], oldX = _ref4[0], oldY = _ref4[1];
            _ref5 = ["65%", "10%"], newX = _ref5[0], newY = _ref5[1];
          } else {
            _ref6 = ["65%", "10%"], oldX = _ref6[0], oldY = _ref6[1];
            _ref7 = ["0%", "50%"], newX = _ref7[0], newY = _ref7[1];
          }
          if (this.skip != null) {
            $div.css({
              top: newY,
              left: newX,
              opacity: .5
            });
            $battlePane.prepend($div);
            return done();
          } else {
            $div.css({
              top: oldY,
              left: oldX,
              opacity: 0
            });
            $div.animate({
              top: newY,
              left: newX,
              opacity: 1
            }, 1000 * this.speed, 'easeOutElastic').delay(1000 * this.speed).animate({
              opacity: .2
            });
            $battlePane.prepend($div);
            return setTimeout(done, 500 * this.speed);
          }
          break;
        case "ReflectAttachment":
          this.cannedText('REFLECT_START', player);
          return this.attachScreen(player, 'blue', 10, done);
        case "LightScreenAttachment":
          this.cannedText('LIGHT_SCREEN_START', player);
          return this.attachScreen(player, 'yellow', 5, done);
        default:
          return done();
      }
    };

    BattleView.prototype.attachBattle = function(attachment, done) {
      return done();
    };

    BattleView.prototype.attachScreen = function(player, slot, klass, offset, done) {
      var $screen, finalSize, halfSize, x, y, _ref, _ref1;
      if (done == null) {
        done = function() {};
      }
      if (arguments.length === 4) {
        _ref = [null, slot, klass, offset], slot = _ref[0], klass = _ref[1], offset = _ref[2], done = _ref[3];
      }
      finalSize = 100;
      halfSize = finalSize >> 1;
      $screen = $("<div/>").addClass("team-screen " + klass + " field-" + player);
      if (slot) {
        $screen.addClass("slot-" + slot);
      }
      _ref1 = this.getPokemonPosition(player, 0), x = _ref1[0], y = _ref1[1];
      x += offset;
      y += offset;
      $screen.css({
        left: x,
        top: y
      }).appendTo(this.$('.battle_pane'));
      if (this.skip != null) {
        $screen.css({
          width: finalSize,
          height: finalSize
        });
        $screen.css({
          x: -halfSize,
          y: -halfSize
        });
        return done();
      } else {
        $screen.transition({
          width: finalSize,
          x: -halfSize
        }, 250 * this.speed, 'easeInOutCubic').transition({
          height: finalSize,
          y: -halfSize
        }, 250 * this.speed, 'easeInOutCubic');
        return setTimeout(done, 500 * this.speed);
      }
    };

    BattleView.prototype.unattachScreen = function(player, slot, klass, done) {
      var $selector, selector, _ref;
      if (done == null) {
        done = function() {};
      }
      if (arguments.length === 3) {
        _ref = [null, slot, klass], slot = _ref[0], klass = _ref[1], done = _ref[2];
      }
      selector = ".team-screen." + klass + ".field-" + player;
      if (slot) {
        selector += ".slot-" + slot;
      }
      $selector = this.$(selector);
      $selector.fadeOut(500 * this.speed, function() {
        return $selector.remove();
      });
      return done();
    };

    BattleView.prototype.boost = function(player, slot, deltaBoosts, options) {
      var $effect, $effects, $pokemon, abbreviatedStat, amount, delta, finalStat, message, negFloatText, pokemon, pokemonName, posFloatText, previous, stages, stat;
      if (options == null) {
        options = {};
      }
      pokemon = this.model.getPokemon(player, slot);
      if (this.isIllusioned(pokemon)) {
        pokemonName = pokemon.getTeam().attributes.pokemon.at(pokemon.getTeam().attributes.pokemon.length - 1).attributes.name;
      } else {
        pokemonName = pokemon.escape('name');
      }
      stages = pokemon.get('stages');
      $pokemon = this.$pokemon(player, slot);
      $effects = $pokemon.find('.pokemon-effects');
      posFloatText = [];
      negFloatText = [];
      for (stat in deltaBoosts) {
        delta = deltaBoosts[stat];
        previous = stages[stat];
        stages[stat] += delta;
        if (!options.silent) {
          message = this.makeBoostMessage(pokemonName, stat, delta, stages[stat]);
          if (message) {
            this.addLog(message);
          }
        }
        abbreviatedStat = (function() {
          switch (stat) {
            case "attack":
              return "Att";
            case "defense":
              return "Def";
            case "speed":
              return "Spe";
            case "specialAttack":
              return "Sp.A";
            case "specialDefense":
              return "Sp.D";
            case "accuracy":
              return "Acc.";
            case "evasion":
              return "Eva.";
            default:
              return stat;
          }
        })();
        amount = stages[stat];
        if (amount > 0) {
          amount = "+" + amount;
        }
        finalStat = "" + amount + " " + abbreviatedStat;
        $effect = this.addPokemonEffect($pokemon, "boost " + stat, finalStat);
        if (amount < 0) {
          $effect.addClass('negative');
          negFloatText.push("" + delta + " " + abbreviatedStat);
        } else if (amount > 0) {
          $effect.removeClass('negative');
          posFloatText.push("+" + delta + " " + abbreviatedStat);
        } else {
          $effect.remove();
        }
      }
      if (options.floatText) {
        if (negFloatText.length > 0) {
          this.floatText(player, slot, negFloatText.join('/'), 'red');
        }
        if (posFloatText.length > 0) {
          this.floatText(player, slot, posFloatText.join('/'));
        }
      }
      return true;
    };

    BattleView.prototype.makeBoostMessage = function(pokemonName, stat, amount, currentBoost) {
      var adverb;
      stat = (function() {
        switch (stat) {
          case "attack":
            return "Attack";
          case "defense":
            return "Defense";
          case "speed":
            return "Speed";
          case "specialAttack":
            return "Special Attack";
          case "specialDefense":
            return "Special Defense";
          case "accuracy":
            return "Accuracy";
          case "evasion":
            return "Evasion";
          default:
            return stat;
        }
      })();
      if (amount > 0) {
        if (amount === 12) {
          return "" + pokemonName + " cut its own HP and maximized its " + stat + "!";
        } else {
          if (amount === 1) {
            adverb = "";
          }
          if (amount === 2) {
            adverb = " sharply";
          }
          if (amount >= 3) {
            adverb = " drastically";
          }
          return "" + pokemonName + "'s " + stat + " rose" + adverb + "!";
        }
      } else if (amount < 0) {
        if (amount === -1) {
          adverb = "";
        }
        if (amount === -2) {
          adverb = " harshly";
        }
        if (amount <= -3) {
          adverb = " severely";
        }
        return "" + pokemonName + "'s " + stat + adverb + " fell!";
      } else if (currentBoost === 6) {
        return "" + pokemonName + "'s " + stat + " won't go any higher!";
      } else if (currentBoost === -6) {
        return "" + pokemonName + "'s " + stat + " won't go any lower!";
      }
    };

    BattleView.prototype.unattachPokemon = function(player, slot, effect, done) {
      var $pokemon, $spriteContainer, $substitute, pokemon;
      pokemon = this.model.getPokemon(player, slot);
      $pokemon = this.$pokemon(player, slot);
      switch (effect) {
        case 'SubstituteAttachment':
          $spriteContainer = this.$spriteContainer(player, slot);
          $spriteContainer.removeClass('fade');
          $substitute = $pokemon.find('.substitute').first();
          if (this.skip != null) {
            $substitute.remove();
            return done();
          } else {
            $substitute.transition({
              y: 300,
              opacity: 0
            }, 300 * this.speed, function() {
              return $substitute.remove();
            });
            return setTimeout(done, 300 * this.speed);
          }
          break;
        case 'ProtectAttachment':
        case 'KingsShieldAttachment':
        case 'SpikyShieldAttachment':
          return this.unattachScreen(player, slot, 'pink', done);
        case 'Air Balloon':
          $pokemon.find(".pokemon-effect.balloon").remove();
          this.addLog("" + (pokemon.escape('name')) + "'s Air Balloon popped!");
          return done();
        case 'ConfusionAttachment':
          $pokemon.find(".pokemon-effect.confusion").remove();
          return done();
        case 'Paralyze':
          pokemon.set('status', null);
          return done();
        case 'Burn':
          pokemon.set('status', null);
          return done();
        case 'Poison':
          pokemon.set('status', null);
          return done();
        case 'Toxic':
          pokemon.set('status', null);
          return done();
        case 'Freeze':
          pokemon.set('status', null);
          return done();
        case 'Sleep':
          pokemon.set('status', null);
          return done();
        default:
          return done();
      }
    };

    BattleView.prototype.setBoosts = function(player, slot, boosts) {
      var pokemon, stages, stat;
      pokemon = this.model.getPokemon(player, slot);
      stages = pokemon.get('stages');
      for (stat in boosts) {
        boosts[stat] -= stages[stat];
      }
      return this.boost(player, slot, boosts, {
        silent: true
      });
    };

    BattleView.prototype.resetBoosts = function(player, slot) {
      var $pokemon, pokemon;
      pokemon = this.model.getPokemon(player, slot);
      pokemon.resetBoosts();
      $pokemon = this.$pokemon(player, slot);
      return $pokemon.find('.boost').remove();
    };

    BattleView.prototype.handlePercent = function(pokemon) {
      var $allHP, $hpText, $info, $pokemon, deltaPercent, percent, player, slot, _ref;
      $pokemon = this.$pokemon(pokemon);
      $info = $pokemon.find(".pokemon-info");
      $allHP = $info.find('.hp');
      $hpText = $info.find('.hp-text');
      percent = pokemon.getPercentHP();
      if (percent <= 20) {
        $allHP.css({
          backgroundColor: "#f00"
        });
      } else if (percent <= 50) {
        $allHP.css({
          backgroundColor: "#ff0"
        });
      } else {
        $allHP.css({
          backgroundColor: "#0f0"
        });
      }
      $allHP.width("" + percent + "%");
      $hpText.text("" + percent + "%");
      deltaPercent = percent - pokemon.previous('percent');
      _ref = [$pokemon.data('team'), $pokemon.data('slot')], player = _ref[0], slot = _ref[1];
      return this.floatPercent(player, slot, deltaPercent);
    };

    BattleView.prototype.handleStatus = function(pokemon, status) {
      var $effects, $pokemon, display;
      $pokemon = this.$pokemon(pokemon);
      if (status != null) {
        $effects = $pokemon.find('.pokemon-effects');
        display = this.mapStatusForDisplay(status);
        return this.addPokemonEffect($pokemon, status, display);
      } else {
        return $pokemon.find(".pokemon-effect." + (pokemon.previous('status'))).remove();
      }
    };

    BattleView.prototype.showSpinner = function() {
      return this.$('.battle_actions .show_spinner').removeClass('hidden');
    };

    BattleView.prototype.mapStatusForDisplay = function(status) {
      switch (status) {
        case "burn":
          return "BRN";
        case "paralyze":
          return "PAR";
        case "poison":
          return "PSN";
        case "toxic":
          return "TOX";
        case "freeze":
          return "FRZ";
        case "sleep":
          return "SLP";
      }
    };

    BattleView.prototype.addPokemonEffect = function($pokemon, klass, text) {
      var $effect, $effects;
      $effects = $pokemon.find(".pokemon-effects");
      $effect = $effects.find(".pokemon-effect." + (klass.replace(/\s+/g, '.')));
      if (!text) {
        return $effect;
      }
      if ($effect.length === 0) {
        $effect = $("<div class='pokemon-effect " + klass + "'>" + text + "</div>");
        $effect.appendTo($effects);
      } else {
        $effect.text(text);
      }
      return $effect;
    };

    BattleView.prototype.unattachTeam = function(player, attachment, done) {
      var $battlePane;
      $battlePane = this.$('.battle_pane');
      switch (attachment) {
        case "StealthRockAttachment":
          $battlePane.find(".field-" + player + ".team-stealth-rock").remove();
          return done();
        case "ToxicSpikesAttachment":
          $battlePane.find(".field-" + player + ".team-toxic-spikes").remove();
          return done();
        case "SpikesAttachment":
          $battlePane.find(".field-" + player + ".team-spikes").remove();
          return done();
        case "StickyWebAttachment":
          $battlePane.find(".field-" + player + ".team-sticky-web").remove();
          return done();
        case 'ReflectAttachment':
          this.cannedText('REFLECT_END', player);
          return this.unattachScreen(player, 'blue', done);
        case 'LightScreenAttachment':
          this.cannedText('LIGHT_SCREEN_END', player);
          return this.unattachScreen(player, 'yellow', done);
        default:
          return done();
      }
    };

    BattleView.prototype.unattachBattle = function(effect, done) {
      return done();
    };

    BattleView.prototype.updateTimers = function(timers) {
      var index, now, timer, _i, _len, _results;
      now = $.now();
      _results = [];
      for (index = _i = 0, _len = timers.length; _i < _len; index = ++_i) {
        timer = timers[index];
        this.timers[index] = timer;
        _results.push(this.timerUpdatedAt[index] = now);
      }
      return _results;
    };

    BattleView.prototype.renderTimers = function() {
      var i, _i, _results;
      _results = [];
      for (i = _i = 0; _i <= 1; i = ++_i) {
        _results.push(this.renderTimer(i));
      }
      return _results;
    };

    BattleView.prototype.countdownTimers = function() {
      var diff;
      this.renderTimers();
      diff = $.now() - this.battleStartTime - this.timerIterations * 1000;
      this.timerIterations++;
      return this.countdownTimersId = setTimeout(this.countdownTimers, 1000 - diff);
    };

    BattleView.prototype.renderTimer = function(index) {
      var $frozenTimer, $info, $remainingTimer, timeRemaining;
      $info = this.$playerInfo(index);
      $remainingTimer = $info.find('.remaining-timer');
      $frozenTimer = $info.find('.frozen-timer');
      timeRemaining = this.timers[index] - $.now() + this.timerUpdatedAt[index];
      if (!timeRemaining && timeRemaining !== 0) {
        $remainingTimer.addClass('hidden');
      } else {
        $remainingTimer.removeClass('hidden');
        $remainingTimer.text(PokeBattle.humanizeTime(timeRemaining));
      }
      if (timeRemaining <= 1 * 60 * 1000) {
        $frozenTimer.addClass("battle-timer-low");
        $remainingTimer.addClass("battle-timer-low");
      } else {
        $frozenTimer.removeClass("battle-timer-low");
        $remainingTimer.removeClass("battle-timer-low");
      }
      if (this.timerFrozenAt[index]) {
        $frozenTimer.text(PokeBattle.humanizeTime(this.timerFrozenAt[index]));
        $frozenTimer.removeClass('hidden');
        $remainingTimer.addClass('battle-timer-small');
        if (this.showSecondaryTimer) {
          return $remainingTimer.removeClass('hidden');
        } else {
          return $remainingTimer.addClass('hidden');
        }
      } else {
        $frozenTimer.addClass('hidden');
        return $remainingTimer.removeClass('battle-timer-small hidden');
      }
    };

    BattleView.prototype.pauseTimer = function(index, timeSinceLastAction) {
      var now;
      now = $.now();
      this.timerFrozenAt[index] = this.timers[index] - (now - this.timerUpdatedAt[index]);
      if (timeSinceLastAction) {
        this.timerUpdatedAt[index] -= timeSinceLastAction;
      }
      this.showSecondaryTimer = timeSinceLastAction != null;
      return this.renderTimer(index);
    };

    BattleView.prototype.resumeTimer = function(index) {
      delete this.timerFrozenAt[index];
      return this.renderTimer(index);
    };

    BattleView.prototype.$playerInfo = function(index) {
      var $userInfo;
      $userInfo = this.$('.battle_user_info');
      if (index === this.model.get('index')) {
        return $userInfo.find('.left');
      } else {
        return $userInfo.find('.right');
      }
    };

    BattleView.prototype.announceWinner = function(player, done) {
      var message, owner;
      owner = this.model.getTeam(player).escape('owner');
      message = "" + owner + " won!";
      return this.announceWin(message, done);
    };

    BattleView.prototype.announceForfeit = function(player, done) {
      var message, owner;
      owner = this.model.getTeam(player).escape('owner');
      message = "" + owner + " has forfeited!";
      return this.announceWin(message, done);
    };

    BattleView.prototype.announceTimer = function(player, done) {
      var message, owner;
      owner = this.model.getTeam(player).escape('owner');
      message = "" + owner + " was given the timer win!";
      return this.announceWin(message, done);
    };

    BattleView.prototype.announceExpiration = function(done) {
      var message;
      message = "The battle expired!";
      return this.announceWin(message, done);
    };

    BattleView.prototype.announceWin = function(message, done) {
      this.chatView.print("<h3>" + message + "</h3>");
      this.addSummary(message, {
        newline: true
      });
      this.model.set('finished', true);
      return done();
    };

    BattleView.prototype.handleEnd = function(battle, end) {
      if (this.shouldRenderEnd()) {
        this.disableButtons();
        this.$('.battle_actions').html(this.battle_end_template({
          window: window
        }));
      }
      return clearTimeout(this.countdownTimersId);
    };

    BattleView.prototype.handleRemoval = function(battle) {
      if (battle === this.model) {
        return this.remove();
      }
    };

    BattleView.prototype.shouldRenderEnd = function() {
      return PokeBattle.primus != null;
    };

    BattleView.prototype.saveReplay = function(e) {
      var $replayButton;
      $replayButton = $(e.currentTarget);
      if ($replayButton.is('.disabled')) {
        return;
      }
      $replayButton.addClass('disabled');
      $replayButton.find('.show_spinner').removeClass('hidden');
      return PokeBattle.primus.send('saveReplay', this.model.id, (function(_this) {
        return function(error, replayId) {
          var absoluteUrl, relativeUrl;
          $replayButton.find('.show_spinner').addClass('hidden');
          if (error) {
            return _this.chatView.announce("error", error);
          } else {
            relativeUrl = "/replays/" + replayId;
            absoluteUrl = "" + window.location.protocol + "//" + window.location.host;
            absoluteUrl += relativeUrl;
            return _this.chatView.announce("success", "Your replay was saved! Share the link: " + absoluteUrl + ".");
          }
        };
      })(this));
    };

    BattleView.prototype.saveLog = function() {
      var $children, blob, fileName, log;
      log = [];
      $children = this.$('.messages').children();
      $children.each(function() {
        var $this, isHeader;
        $this = $(this);
        isHeader = /H\d/i.test(this.tagName);
        if (isHeader) {
          log.push("");
        }
        log.push($this.text());
        if (isHeader) {
          return log.push("");
        }
      });
      log = [log.join('\n')];
      fileName = (this.model.get('teams').map(function(team) {
        return team.escape('owner');
      })).join(" vs ");
      fileName += ".txt";
      blob = new Blob(log, {
        type: "text/plain;charset=utf-8",
        endings: "native"
      });
      return saveAs(blob, fileName);
    };

    BattleView.prototype.returnToLobby = function() {
      return PokeBattle.navigation.focusLobby();
    };

    BattleView.prototype.changeBattleSpeed = function(e) {
      this.speed = Number($(e.currentTarget).val()) || 1;
      try {
        return window.localStorage.setItem('battle_speed', this.speed);
      } catch (_error) {

      }
    };

    BattleView.prototype.$pokemon = function(player, slot) {
      var pokemon;
      if (arguments.length === 1) {
        pokemon = player;
        this.model.get('teams').forEach(function(team, playerIndex) {
          var index;
          index = team.indexOf(pokemon);
          if (index !== -1) {
            player = playerIndex;
            slot = index;
          }
        });
      }
      return this.$(".pokemon[data-team='" + player + "'][data-slot='" + slot + "']");
    };

    BattleView.prototype.$spriteContainer = function(player, slot) {
      return this.$pokemon(player, slot).find('.sprite');
    };

    BattleView.prototype.$sprite = function(player, slot) {
      return this.$spriteContainer(player, slot).find('img');
    };

    BattleView.prototype.$projectile = function(player, slot, moveData) {
      var $projectile, x, y, _ref;
      $projectile = $('<div/>').addClass('projectile');
      $projectile.addClass(moveData['type'].toLowerCase());
      $projectile.appendTo(this.$(".battle_pane"));
      _ref = this.getPokemonPosition(player, slot), x = _ref[0], y = _ref[1];
      $projectile.css({
        left: x,
        top: y
      });
      return $projectile;
    };

    BattleView.prototype.isFront = function(player) {
      return this.model.get('index') !== player;
    };

    BattleView.prototype.faint = function(player, slot, done) {
      var $pokemon, $sprite;
      $pokemon = this.$pokemon(player, slot);
      $sprite = this.$sprite(player, slot);
      if (this.skip != null) {
        $sprite.popover('destroy');
        $sprite.remove();
        done();
        return;
      }
      $sprite.transition({
        y: 100,
        opacity: 0
      }, 250 * this.speed, 'ease-in', function() {
        $sprite.popover('destroy');
        return $sprite.remove();
      });
      setTimeout(done, 250 * this.speed);
      return this.renderUserInfo();
    };

    BattleView.prototype.resetPopovers = function() {
      var $pokemon, $sprite, player, pokemon, slot, _i, _results;
      if (!this.model.teams) {
        return;
      }
      _results = [];
      for (player = _i = 0; _i < 2; player = ++_i) {
        _results.push((function() {
          var _j, _ref, _results1;
          _results1 = [];
          for (slot = _j = 0, _ref = this.model.numActive; 0 <= _ref ? _j < _ref : _j > _ref; slot = 0 <= _ref ? ++_j : --_j) {
            $pokemon = this.$pokemon(player, slot);
            pokemon = this.model.getPokemon(player, slot);
            $sprite = this.$sprite(player, slot);
            $sprite.popover('destroy');
            _results1.push(this.pokemonPopover($sprite, pokemon));
          }
          return _results1;
        }).call(this));
      }
      return _results;
    };

    BattleView.prototype.enableButtons = function(validActions) {
      if (validActions) {
        this.renderActions(validActions);
        return this.resumeTimer(this.model.get('index'));
      } else {
        return this.disableButtons();
      }
    };

    BattleView.prototype.disableButtons = function() {
      this.$('.battle_actions .switch.button').popover('destroy');
      return this.renderWaiting();
    };

    BattleView.prototype.addMoveMessage = function(owner, pokemon, moveName) {
      var lastpokemon;
      if (this.isIllusioned(pokemon)) {
        lastpokemon = pokemon.getTeam().attributes.pokemon.at(pokemon.getTeam().attributes.pokemon.length - 1);
        pokemon = lastpokemon;
      }
      this.chatView.print("<p class='move_message'>" + owner + "'s " + (this.pokemonHtml(pokemon)) + " used <strong>" + moveName + "</strong>!</p>");
      return this.addSummary("" + owner + "'s " + (pokemon.escape('name')) + " used <strong>" + moveName + "</strong>!", {
        newline: true,
        big: true
      });
    };

    BattleView.prototype.isIllusioned = function(pokemon) {
      var illusionmons, _ref;
      illusionmons = ['Zoroark', 'Zorua'];
      if ((_ref = pokemon.attributes.species, __indexOf.call(illusionmons, _ref) >= 0) && pokemon.attributes.percent === 100 && this.model.attributes.turn <= 1) {
        return true;
      }
      if (pokemon.getIllu()) {
        return true;
      }
      return false;
    };

    BattleView.prototype.addLog = function(message) {
      return this.chatView.print("<p>" + message + "</p>");
    };

    BattleView.prototype.addSummary = function(message, options) {
      var $p, $summary, html, removeP;
      if (options == null) {
        options = {};
      }
      if (this.skip != null) {
        return;
      }
      $summary = this.$('.battle_summary');
      $summary.show();
      $p = $summary.children().last();
      if ($p.length === 0 || $p.is('.newline') || options.newline) {
        $p = $("<p/>").html(message).hide();
        if (options.newline) {
          $p.addClass('newline');
        }
        if (options.big) {
          $p.addClass('big');
        }
        $p.appendTo($summary);
      } else {
        html = $p.html();
        $p.html("" + html + " " + message);
      }
      $p.slideDown(200);
      if (!this.chatView.$el.is(':visible')) {
        return;
      }
      removeP = function() {
        return $p.slideUp(200, function() {
          $p.remove();
          if ($summary.is(':empty')) {
            return $summary.hide();
          }
        });
      };
      return setTimeout(removeP, 4000);
    };

    BattleView.prototype.beginTurn = function(turn, done) {
      this.chatView.print("<h2>Turn " + turn + "</h2>");
      this.model.set('turn', turn);
      return done();
    };

    BattleView.prototype.continueTurn = function(done) {
      var offset;
      this.$('.battle_summary').empty().hide();
      offset = this.$('.battle_pane').offset().top + this.$el.scrollTop();
      offset -= this.$el.offset().top;
      this.$el.scrollTop(offset);
      return done();
    };

    BattleView.prototype.makeMove = function(e) {
      var $target, forSlot, moveName, pokemon;
      forSlot = 0;
      $target = $(e.currentTarget);
      moveName = $target.data('move-id');
      if ($target.hasClass('disabled')) {
        console.log("Cannot use " + moveName + ".");
        return;
      }
      console.log("Making move " + moveName);
      pokemon = this.model.getPokemon(this.model.get('index'), 0);
      this.showSpinner();
      return this.model.makeMove(moveName, forSlot, this.afterSelection.bind(this, pokemon));
    };

    BattleView.prototype.switchPokemon = function(e) {
      var $target, forSlot, pokemon, toSlot;
      forSlot = 0;
      $target = $(e.currentTarget);
      toSlot = $target.data('slot');
      if ($target.hasClass('disabled')) {
        console.log("Cannot switch to " + toSlot + ".");
        return;
      }
      console.log("Switching to " + toSlot);
      toSlot = parseInt(toSlot, 10);
      pokemon = this.model.getPokemon(this.model.get('index'), 0);
      this.showSpinner();
      return this.model.makeSwitch(toSlot, forSlot, this.afterSelection.bind(this, pokemon));
    };

    BattleView.prototype.cancelAction = function(e) {
      var pokemon;
      this.$('.battle_actions').html("<div class=\"well well-battle-actions\">Canceling...</div>");
      pokemon = this.model.getPokemon(this.model.get('index'), 0);
      this.model.makeCancel();
      return this.afterAction(pokemon);
    };

    BattleView.prototype.megaEvolve = function(e) {
      var $target, pokemon;
      $target = $(e.currentTarget);
      $target.toggleClass('pressed');
      pokemon = this.model.getPokemon(this.model.get('index'), 0);
      return pokemon.set('megaEvolve', $target.hasClass("pressed"));
    };

    BattleView.prototype.afterSelection = function(pokemon) {
      this.disableButtons();
      this.pauseTimer(this.model.get('index'), 0);
      return this.afterAction(pokemon);
    };

    BattleView.prototype.afterAction = function(pokemon) {
      return pokemon.set('megaEvolve', false);
    };

    BattleView.prototype.preloadImages = function() {
      var gen, image, pokemonUrl, pokemonUrls, teams, _i, _len, _results;
      gen = window.Generations[this.model.get('generation').toUpperCase()];
      teams = this.model.get('teams').map((function(_this) {
        return function(team, playerIndex) {
          var front;
          front = _this.isFront(playerIndex);
          return team.get('pokemon').map(function(pokemon) {
            var forme, formeName, formeNames, formes, id, shiny, species, _i, _len, _results;
            species = pokemon.get('species');
            forme = pokemon.get('forme');
            shiny = pokemon.get('shiny');
            id = gen.SpeciesData[species].id;
            formes = gen.FormeData[species];
            formeNames = _.keys(formes);
            formeNames = _.filter(formeNames, function(formeName) {
              return forme === formeName || formes[formeName].isBattleOnly;
            });
            _results = [];
            for (_i = 0, _len = formeNames.length; _i < _len; _i++) {
              formeName = formeNames[_i];
              _results.push(PokemonSprite(id, formeName, {
                front: front,
                shiny: shiny
              }));
            }
            return _results;
          });
        };
      })(this));
      pokemonUrls = _.flatten(_.zip.apply(_, teams));
      _results = [];
      for (_i = 0, _len = pokemonUrls.length; _i < _len; _i++) {
        pokemonUrl = pokemonUrls[_i];
        image = new Image();
        _results.push(image.src = pokemonUrl);
      }
      return _results;
    };

    BattleView.prototype.addPokemonImage = function($div, url, options) {
      var $image, image, scale;
      if (options == null) {
        options = {};
      }
      scale = options.scale || 1;
      image = new Image();
      $image = $(image);
      $image.load((function(_this) {
        return function() {
          var height, width;
          width = image.width, height = image.height;
          if (scale !== 1) {
            width *= scale;
            height *= scale;
            $image.width(width);
            $image.height(height);
          }
          return typeof options.callback === "function" ? options.callback($image) : void 0;
        };
      })(this));
      image.src = url;
      return $image.hide().appendTo($div);
    };

    BattleView.prototype.getPokemonPosition = function(player, slot) {
      if (player === this.model.get('index')) {
        return [96, 208];
      } else {
        return [332, 108];
      }
    };

    BattleView.prototype.remove = function() {
      clearTimeout(this.countdownTimersId);
      return BattleView.__super__.remove.call(this);
    };

    BattleView.prototype.pokemonHtml = function(pokemon) {
      return "<a class='pokemon-link' href='" + (pokemon.getPokedexUrl()) + "' target='_blank'>" + (pokemon.escape('name')) + "</a>";
    };

    BattleView.prototype.setVisibleTeam = function() {
      var battle;
      battle = this.model;
      return battle.set('visibleteam', true);
    };

    return BattleView;

  })(Backbone.View);

}).call(this);

(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  this.ChatView = (function(_super) {
    var MAX_MESSAGES_LENGTH, MAX_USERNAME_HISTORY;

    __extends(ChatView, _super);

    function ChatView() {
      this.scrollToBottom = __bind(this.scrollToBottom, this);
      this.isAtBottom = __bind(this.isAtBottom, this);
      this.linkify = __bind(this.linkify, this);
      this.sanitize = __bind(this.sanitize, this);
      this.timestamp = __bind(this.timestamp, this);
      this.clear = __bind(this.clear, this);
      this.print = __bind(this.print, this);
      this.announce = __bind(this.announce, this);
      this.cleanChat = __bind(this.cleanChat, this);
      this.rawMessage = __bind(this.rawMessage, this);
      this.userLeave = __bind(this.userLeave, this);
      this.userJoin = __bind(this.userJoin, this);
      this.handleMessage = __bind(this.handleMessage, this);
      this.userColor = __bind(this.userColor, this);
      this.userMessage = __bind(this.userMessage, this);
      this.handleKeys = __bind(this.handleKeys, this);
      this.tabComplete = __bind(this.tabComplete, this);
      this.sendChat = __bind(this.sendChat, this);
      this.focusChat = __bind(this.focusChat, this);
      this.getSelectedText = __bind(this.getSelectedText, this);
      this.renderUserList = __bind(this.renderUserList, this);
      this.render = __bind(this.render, this);
      this.setTopic = __bind(this.setTopic, this);
      this.initialize = __bind(this.initialize, this);
      return ChatView.__super__.constructor.apply(this, arguments);
    }

    ChatView.prototype.template = JST['chat'];

    ChatView.prototype.userListTemplate = JST['user_list'];

    ChatView.prototype.events = {
      'click': 'focusChat',
      'keydown .chat_input': 'handleKeys',
      'click .chat_input_send': 'sendChat',
      'scroll_to_bottom': 'scrollToBottom'
    };

    MAX_USERNAME_HISTORY = 10;

    MAX_MESSAGES_LENGTH = 500;

    ChatView.prototype.initialize = function(options) {
      var callback, eventName, _i, _len, _ref;
      this.noisy = options.noisy;
      if (this.model) {
        this.listenTo(this.model.get('users'), 'add remove reset', this.renderUserList);
        if (this.noisy) {
          this.listenTo(this.model.get('users'), 'add', this.userJoin);
          this.listenTo(this.model.get('users'), 'remove', this.userLeave);
        }
        _ref = Room.prototype.EVENTS;
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          eventName = _ref[_i];
          callback = this[eventName] || (function() {
            throw new Error("ChatView must implement " + eventName + ".");
          })();
          this.listenTo(this.model, eventName, callback);
        }
      }
      this.chatHistory = [];
      this.mostRecentNames = [];
      this.tabCompleteIndex = -1;
      return this.tabCompleteNames = [];
    };

    ChatView.prototype.setTopic = function(topic) {
      topic = this.sanitize(topic);
      return this.rawMessage("<div class='alert alert-info'><b>Topic:</b> " + topic + "</div>");
    };

    ChatView.prototype.render = function() {
      this.$el.html(this.template());
      if (this.model) {
        this.$el.removeClass('without_spectators');
        this.$el.removeClass('without_chat_input');
        this.renderUserList();
      }
      return this;
    };

    ChatView.prototype.renderUserList = function() {
      this.$('.user_count').text("Users (" + (this.model.get('users').length) + ")");
      this.$('.users').html(this.userListTemplate({
        userList: this.model.get('users').models
      }));
      return this;
    };

    ChatView.prototype.getSelectedText = function() {
      var text;
      text = "";
      if (window.getSelection) {
        text = window.getSelection().toString();
      } else if (document.selection && document.selection.type !== "Control") {
        text = document.selection.createRange().text;
      }
      return text;
    };

    ChatView.prototype.focusChat = function() {
      var selectedText;
      selectedText = this.getSelectedText();
      if (selectedText.length === 0) {
        return this.$('.chat_input').focus();
      }
    };

    ChatView.prototype.sendChat = function() {
      var $this, message;
      $this = this.$('.chat_input');
      message = $this.val();
      if (this.model.sendChat(message)) {
        this.chatHistory.push(message);
        delete this.chatHistoryIndex;
        return $this.val('');
      }
    };

    ChatView.prototype.tabComplete = function($input, options) {
      var candidates, cursorIndex, length, newPrefix, newPrefixLength, pieces, possibleName, rest, tabbedName, text;
      if (options == null) {
        options = {};
      }
      cursorIndex = $input.prop('selectionStart');
      text = $input.val();
      if (this.tabCompleteNames.length > 0 && this.tabCompleteCursorIndex === cursorIndex) {
        if (options.reverse) {
          this.tabCompleteIndex -= 1;
          if (this.tabCompleteIndex < 0) {
            this.tabCompleteIndex = this.tabCompleteNames.length - 1;
          }
        } else {
          this.tabCompleteIndex = (this.tabCompleteIndex + 1) % this.tabCompleteNames.length;
        }
      } else {
        delete this.tabCompleteCursorIndex;
        pieces = text.slice(0, cursorIndex).split(' ');
        possibleName = pieces.pop();
        rest = pieces.join(' ');
        if (pieces.length > 0) {
          rest += ' ';
        }
        length = possibleName.length;
        if (length === 0) {
          return;
        }
        candidates = _.union(this.mostRecentNames, this.model.get('users').pluck('id'));
        candidates = candidates.filter(function(name) {
          return name.slice(0, length).toLowerCase() === possibleName.toLowerCase();
        });
        if (candidates.length === 0) {
          return;
        }
        if (options.reverse) {
          this.tabCompleteIndex = candidates.length - 1;
        } else {
          this.tabCompleteIndex = 0;
        }
        this.tabCompleteNames = candidates;
        this.tabCompletePrefix = rest;
        this.tabCompleteCursorIndex = cursorIndex;
      }
      tabbedName = this.tabCompleteNames[this.tabCompleteIndex];
      newPrefix = this.tabCompletePrefix + tabbedName;
      newPrefixLength = newPrefix.length;
      $input.val(newPrefix + text.slice(cursorIndex));
      $input[0].setSelectionRange(newPrefixLength, newPrefixLength);
      return this.tabCompleteCursorIndex = newPrefixLength;
    };

    ChatView.prototype.handleKeys = function(e) {
      var $input;
      $input = $(e.currentTarget);
      switch (e.which) {
        case 13:
          e.preventDefault();
          return this.sendChat();
        case 9:
          e.preventDefault();
          return this.tabComplete($input, {
            reverse: e.shiftKey
          });
        case 38:
          e.preventDefault();
          if (this.chatHistory.length === 0) {
            return;
          }
          if (this.chatHistoryIndex == null) {
            this.chatHistoryIndex = this.chatHistory.length;
            this.chatHistoryText = $input.val();
          }
          if (this.chatHistoryIndex > 0) {
            this.chatHistoryIndex -= 1;
            return $input.val(this.chatHistory[this.chatHistoryIndex]);
          }
          break;
        case 40:
          e.preventDefault();
          if (this.chatHistoryIndex == null) {
            return;
          }
          this.chatHistoryIndex += 1;
          if (this.chatHistoryIndex === this.chatHistory.length) {
            $input.val(this.chatHistoryText);
            return delete this.chatHistoryIndex;
          } else {
            return $input.val(this.chatHistory[this.chatHistoryIndex]);
          }
      }
    };

    ChatView.prototype.userMessage = function(username, message) {
      var displayName, highlight, index, u, user, yourName;
      user = this.model.get('users').get(username);
      displayName = (user != null ? user.getDisplayName() : void 0) || username;
      yourName = PokeBattle.username;
      highlight = new RegExp("\\b" + yourName + "\\b", 'i').test(message);
      u = "<b class='open_pm fake_link' data-user-id='" + username + "' style='color: " + (this.userColor(username)) + "'>" + displayName + ":</b>";
      this.rawMessage("" + (this.timestamp()) + " " + u + " " + (this.sanitize(message)), {
        highlight: highlight
      });
      this.handleMessage(user, message);
      index = this.mostRecentNames.indexOf(username);
      if (index !== -1) {
        this.mostRecentNames.splice(index, 1);
      }
      this.mostRecentNames.push(username);
      if (this.mostRecentNames.length > MAX_USERNAME_HISTORY) {
        return this.mostRecentNames.shift();
      }
    };

    ChatView.prototype.userColor = function(username) {
      var c, chr, h, hash, i, l, s, _i, _len;
      hash = 0;
      for (i = _i = 0, _len = username.length; _i < _len; i = ++_i) {
        c = username[i];
        chr = username.charCodeAt(i);
        hash = ((hash << 5) - hash) + chr;
        hash |= 0;
      }
      h = hash % 360;
      hash /= 360;
      s = (hash % 25) + 75;
      l = 50;
      return "hsl(" + h + ", " + s + "%, " + l + "%)";
    };

    ChatView.prototype.handleMessage = function(user, message) {
      var authority, printableCommands, _ref;
      authority = user != null ? user.get('authority') : void 0;
      printableCommands = ['/pbv', '/data'];
      if (authority > 1 && (_ref = message.split(/\s/, 1)[0], __indexOf.call(printableCommands, _ref) >= 0)) {
        return PokeBattle.commands.execute(this.model, message);
      }
    };

    ChatView.prototype.userJoin = function(user) {
      return this.rawMessage("" + (this.timestamp()) + " " + user.id + " joined!");
    };

    ChatView.prototype.userLeave = function(user) {
      return this.rawMessage("" + (this.timestamp()) + " " + user.id + " left!");
    };

    ChatView.prototype.rawMessage = function(message, options) {
      var klass, wasAtBottom;
      if (options == null) {
        options = {};
      }
      wasAtBottom = this.isAtBottom();
      klass = [];
      if (options.highlight) {
        klass.push('bg-blue');
      }
      if (options["class"]) {
        klass.push(options["class"]);
      }
      this.print("<p class='chat_message " + (klass.join(' ')) + "'>" + message + "</p>");
      this.cleanChat();
      if (wasAtBottom) {
        return this.scrollToBottom();
      }
    };

    ChatView.prototype.cleanChat = function() {
      var $messages, numToRemove;
      $messages = this.$('.chat_message');
      numToRemove = $messages.length - MAX_MESSAGES_LENGTH;
      if (numToRemove > 0) {
        return $messages.slice(0, numToRemove).remove();
      }
    };

    ChatView.prototype.announce = function(klass, message) {
      var wasAtBottom;
      wasAtBottom = this.isAtBottom();
      message = this.linkify(message);
      this.print("<div class='alert alert-" + klass + " clearfix'>" + message + "</div>");
      if (wasAtBottom) {
        return this.scrollToBottom();
      }
    };

    ChatView.prototype.print = function(message) {
      return this.$('.messages').append(message);
    };

    ChatView.prototype.clear = function() {
      return this.$('.messages').empty();
    };

    ChatView.prototype.timestamp = function() {
      var date, hours, minutes, seconds;
      date = new Date();
      hours = date.getHours();
      minutes = date.getMinutes();
      seconds = date.getSeconds();
      minutes = ("00" + minutes).substr(-2);
      seconds = ("00" + seconds).substr(-2);
      return "<span class='monospace'>[" + hours + ":" + minutes + ":" + seconds + "]</span>";
    };

    ChatView.prototype.sanitize = function(message) {
      var sanitizedMessage;
      sanitizedMessage = $('<div/>').text(message).html();
      return this.linkify(sanitizedMessage);
    };

    ChatView.prototype.linkify = function(message) {
      message = URI.withinString(message, function(url) {
        var $a, battleId, battleRegex, host, path, uri, _ref;
        uri = URI(url);
        _ref = [uri.host(), uri.path()], host = _ref[0], path = _ref[1];
        battleRegex = /^\/battles\/([a-fA-F0-9]+)$/i;
        $a = $("<a/>").prop('href', url).prop('target', '_blank').text(url);
        if (host === URI(window.location.href).host() && battleRegex.test(path)) {
          battleId = path.match(battleRegex)[1];
          $a.addClass('spectate').attr('data-battle-id', battleId);
        }
        return $a.wrap("<div/>").parent().html();
      });
      return message;
    };

    ChatView.prototype.isAtBottom = function() {
      var $el;
      $el = this.$('.messages');
      return $el[0].scrollHeight - $el.scrollTop() <= $el.outerHeight();
    };

    ChatView.prototype.scrollToBottom = function() {
      var messages;
      messages = this.$('.messages')[0];
      messages.scrollTop = messages.scrollHeight;
      return false;
    };

    return ChatView;

  })(Backbone.View);

}).call(this);

(function() {
  var attachSelectize, isMobileOrAndroid, setSelectizeDisabled, setSelectizeValue,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  isMobileOrAndroid = function() {
    if (/Mobile/i.test(window.navigator.userAgent)) {
      return true;
    }
    if (/Android/i.test(window.navigator.userAgent)) {
      return true;
    }
    return false;
  };

  attachSelectize = function($element, options) {
    if (isMobileOrAndroid()) {
      return;
    }
    return $element.selectize(options);
  };

  setSelectizeValue = function($element, value) {
    if (isMobileOrAndroid()) {
      return $element.val(value);
    } else {
      return $element.each(function() {
        var _ref;
        return (_ref = this.selectize) != null ? _ref.setValue(value) : void 0;
      });
    }
  };

  setSelectizeDisabled = function($element, disabled) {
    return $element.filter(".selectized").each(function() {
      if (!this.selectize) {
        return;
      }
      if (disabled) {
        return this.selectize.disable();
      } else {
        return this.selectize.enable();
      }
    });
  };

  this.PokemonEditView = (function(_super) {
    __extends(PokemonEditView, _super);

    function PokemonEditView() {
      this.renderMoves = __bind(this.renderMoves, this);
      this.renderStats = __bind(this.renderStats, this);
      this.renderNonStats = __bind(this.renderNonStats, this);
      this.getTeam = __bind(this.getTeam, this);
      this.renderSpecies = __bind(this.renderSpecies, this);
      this.renderFormat = __bind(this.renderFormat, this);
      this.renderTier = __bind(this.renderTier, this);
      this.renderPBV = __bind(this.renderPBV, this);
      this.renderPokemon = __bind(this.renderPokemon, this);
      this.render = __bind(this.render, this);
      this.disableEventsAndExecute = __bind(this.disableEventsAndExecute, this);
      this.filterMovesBy = __bind(this.filterMovesBy, this);
      this.keydownMoves = __bind(this.keydownMoves, this);
      this.buttonify = __bind(this.buttonify, this);
      this.removeSelectedMove = __bind(this.removeSelectedMove, this);
      this.clickSelectedMove = __bind(this.clickSelectedMove, this);
      this.$selectedMove = __bind(this.$selectedMove, this);
      this.recordMoves = __bind(this.recordMoves, this);
      this.insertMove = __bind(this.insertMove, this);
      this.clickMoveName = __bind(this.clickMoveName, this);
      this.blurMoves = __bind(this.blurMoves, this);
      this.preventBlurMoves = __bind(this.preventBlurMoves, this);
      this.changeHiddenPower = __bind(this.changeHiddenPower, this);
      this.changeEv = __bind(this.changeEv, this);
      this.focusEv = __bind(this.focusEv, this);
      this.changeIv = __bind(this.changeIv, this);
      this.changeLevel = __bind(this.changeLevel, this);
      this.changeGender = __bind(this.changeGender, this);
      this.changeItem = __bind(this.changeItem, this);
      this.changeAbility = __bind(this.changeAbility, this);
      this.changeNature = __bind(this.changeNature, this);
      this.changeForme = __bind(this.changeForme, this);
      this.changeHappiness = __bind(this.changeHappiness, this);
      this.changeShiny = __bind(this.changeShiny, this);
      this.changeNickname = __bind(this.changeNickname, this);
      this.changeSpecies = __bind(this.changeSpecies, this);
      this.setTeamTier = __bind(this.setTeamTier, this);
      this.setTeamPBV = __bind(this.setTeamPBV, this);
      this.setPokemon = __bind(this.setPokemon, this);
      this.setGeneration = __bind(this.setGeneration, this);
      this.sortSpecieslist = __bind(this.sortSpecieslist, this);
      this.changeSort = __bind(this.changeSort, this);
      this.setFormat = __bind(this.setFormat, this);
      this.initialize = __bind(this.initialize, this);
      return PokemonEditView.__super__.constructor.apply(this, arguments);
    }

    PokemonEditView.prototype.editTemplate = JST['teambuilder/pokemon'];

    PokemonEditView.prototype.speciesTemplate = JST['teambuilder/species'];

    PokemonEditView.prototype.nonStatsTemplate = JST['teambuilder/non_stats'];

    PokemonEditView.prototype.movesTemplate = JST['teambuilder/moves'];

    PokemonEditView.prototype.events = {
      'change .sortSpecies': 'changeSort',
      'change .species_list': 'changeSpecies',
      'change .selected_nickname': 'changeNickname',
      'click .selected_shininess': 'changeShiny',
      'click .selected_happiness': 'changeHappiness',
      'change .selected-forme': 'changeForme',
      'change .selected_nature': 'changeNature',
      'change .selected_ability': 'changeAbility',
      'change .selected_item': 'changeItem',
      'change .selected_gender': 'changeGender',
      'change .selected_level': 'changeLevel',
      'change .iv-entry': 'changeIv',
      'focus .ev-entry': 'focusEv',
      'blur .ev-entry': 'changeEv',
      'change .ev-entry': 'changeEv',
      'input .ev-entry[type=range]': 'changeEv',
      'change .select-hidden-power': 'changeHiddenPower',
      'keydown .selected_moves input': 'keydownMoves',
      'blur .selected_moves input': 'blurMoves',
      'click .table-moves tbody tr': 'clickMoveName',
      'mousedown .table-moves': 'preventBlurMoves',
      'click .move-button': 'clickSelectedMove',
      'click .move-button .close': 'removeSelectedMove'
    };

    PokemonEditView.prototype.initialize = function(attributes) {
      if (attributes == null) {
        attributes = {};
      }
      return this.onPokemonChange = attributes.onPokemonChange;
    };

    PokemonEditView.prototype.setFormat = function(format) {
      var allformats;
      allformats = window.PokeBattle.conditions.Formats();
      format = allformats[format] || allformats[DEFAULT_FORMAT];
      return this.setGeneration(format.generation);
    };

    PokemonEditView.prototype.changeSort = function(e) {
      var sort;
      sort = $(e.currentTarget).val();
      if (sort === "Default Sort") {
        return this.sortSpecieslist("Default");
      } else if (sort === "Sort by Dexnumber") {
        return this.sortSpecieslist("id", false);
      } else if (sort === "Invert by Dexnumber") {
        return this.sortSpecieslist("id", true);
      } else if (sort === "Sort Alphabetically") {
        return this.sortSpecieslist("pokename", false);
      } else if (sort === "Invert Alphabetically") {
        return this.sortSpecieslist("pokename", true);
      }
    };

    PokemonEditView.prototype.sortSpecieslist = function(option, reverse) {
      var ItemData, MoveData, SpeciesData, data, sortedlist, species, _ref;
      _ref = this.generation, MoveData = _ref.MoveData, SpeciesData = _ref.SpeciesData, ItemData = _ref.ItemData;
      if (option === "Default") {
        sortedlist = this.getSpecies();
      } else {
        sortedlist = this.sortObject(SpeciesData, option, reverse);
      }
      this.speciesList = (function() {
        var _results;
        _results = [];
        for (species in sortedlist) {
          data = sortedlist[species];
          _results.push(species);
        }
        return _results;
      })();
      return this.render();
    };

    PokemonEditView.prototype.sortObject = function(data, option, reverse) {
      var arr, finished, key, newobj, thing, val, _i, _len;
      arr = [];
      for (key in data) {
        val = data[key];
        val.pokename = key;
        arr.push(val);
      }
      arr = _.sortBy(arr, option);
      if (reverse === true) {
        arr.reverse();
      }
      newobj = {};
      for (_i = 0, _len = arr.length; _i < _len; _i++) {
        thing = arr[_i];
        newobj[thing.pokename] = thing;
      }
      return finished = newobj;
    };

    PokemonEditView.prototype.setGeneration = function(generation) {
      var ItemData, MoveData, SpeciesData, data, itemName, species, _ref;
      this.generation = window.Generations[generation.toUpperCase()];
      _ref = this.generation, MoveData = _ref.MoveData, SpeciesData = _ref.SpeciesData, ItemData = _ref.ItemData;
      this.moveData = MoveData;
      this.speciesList = (function() {
        var _results;
        _results = [];
        for (species in SpeciesData) {
          data = SpeciesData[species];
          _results.push(species);
        }
        return _results;
      })();
      this.itemList = _((function() {
        var _results;
        _results = [];
        for (itemName in ItemData) {
          data = ItemData[itemName];
          _results.push(itemName);
        }
        return _results;
      })()).sort();
      return this.render();
    };

    PokemonEditView.prototype.setPokemon = function(pokemon) {
      if (this.pokemon) {
        this.stopListening(this.pokemon);
      }
      this.pokemon = pokemon;
      this.listenTo(pokemon, 'change:level', this.renderStats);
      this.listenTo(pokemon, 'change:ivs', this.renderStats);
      this.listenTo(pokemon, 'change:evs', this.renderStats);
      this.listenTo(pokemon, 'change:nature', this.renderStats);
      this.listenTo(pokemon, 'change:hiddenPowerType', this.renderStats);
      this.listenTo(pokemon, 'change:shiny', this.renderSpecies);
      return this.renderPokemon();
    };

    PokemonEditView.prototype.setTeamPBV = function(pbv) {
      return this.teamPBV = pbv;
    };

    PokemonEditView.prototype.setTeamTier = function(tier) {
      return this.teamTier = tier;
    };

    PokemonEditView.prototype.changeSpecies = function(e) {
      var species;
      if (!this.onPokemonChange) {
        return;
      }
      species = $(e.currentTarget).val();
      this.pokemon = species ? new Pokemon({
        teambuilder: true,
        species: species
      }) : new NullPokemon();
      return this.onPokemonChange(this.pokemon);
    };

    PokemonEditView.prototype.changeNickname = function(e) {
      var $input;
      $input = $(e.currentTarget);
      return this.pokemon.set("name", $input.val());
    };

    PokemonEditView.prototype.changeShiny = function(e) {
      var $switch;
      $switch = $(e.currentTarget).toggleClass("selected");
      return this.pokemon.set("shiny", $switch.is(".selected"));
    };

    PokemonEditView.prototype.changeHappiness = function(e) {
      var $switch, happiness;
      $switch = $(e.currentTarget).toggleClass("selected");
      happiness = $switch.is(".selected") ? 0 : 100;
      return this.pokemon.set("happiness", happiness);
    };

    PokemonEditView.prototype.changeForme = function(e) {
      var $forme;
      $forme = $(e.currentTarget);
      this.pokemon.set('forme', $forme.val());
      return this.pokemon.set('ability', this.pokemon.getAbilities()[0]);
    };

    PokemonEditView.prototype.changeNature = function(e) {
      var $list;
      $list = $(e.currentTarget);
      return this.pokemon.set("nature", $list.val());
    };

    PokemonEditView.prototype.changeAbility = function(e) {
      var $list;
      $list = $(e.currentTarget);
      return this.pokemon.set("ability", $list.val());
    };

    PokemonEditView.prototype.changeItem = function(e) {
      var $list;
      $list = $(e.currentTarget);
      return this.pokemon.set("item", $list.val());
    };

    PokemonEditView.prototype.changeGender = function(e) {
      var $list;
      $list = $(e.currentTarget);
      return this.pokemon.set("gender", $list.val());
    };

    PokemonEditView.prototype.changeLevel = function(e) {
      var $input, value;
      $input = $(e.currentTarget);
      value = parseInt($input.val(), 10);
      if (isNaN(value) || value > 120) {
        value = 1120;
      }
      if (value < 1) {
        value = 1;
      }
      $input.val(value);
      return this.pokemon.set("level", value);
    };

    PokemonEditView.prototype.changeIv = function(e) {
      var $input, stat, value;
      $input = $(e.currentTarget);
      stat = $input.data("stat");
      value = parseInt($input.val(), 10);
      if (isNaN(value) || value > 31 || value < 0) {
        value = 31;
      }
      return this.pokemon.setIv(stat, value);
    };

    PokemonEditView.prototype.focusEv = function(e) {
      var $input, value;
      $input = $(e.currentTarget);
      if ($input.is("[type=range]")) {
        return;
      }
      value = parseInt($input.val(), 10);
      if (value === 0) {
        return $input.val("");
      }
    };

    PokemonEditView.prototype.changeEv = function(e) {
      var $input, stat, value;
      $input = $(e.currentTarget);
      stat = $input.data("stat");
      value = parseInt($input.val(), 10);
      if (value > 252) {
        value = 252;
      }
      if (isNaN(value) || value < 0) {
        value = 0;
      }
      value = this.pokemon.setEv(stat, value);
      if (!$input.is("[type=range]")) {
        return $input.val(value);
      }
    };

    PokemonEditView.prototype.changeHiddenPower = function(e) {
      var $input, type;
      $input = $(e.currentTarget);
      type = $input.val();
      return this.pokemon.set('hiddenPowerType', type.toLowerCase());
    };

    PokemonEditView.prototype.preventBlurMoves = function(e) {
      this._preventBlur = true;
      return _.defer((function(_this) {
        return function() {
          return _this._preventBlur = false;
        };
      })(this));
    };

    PokemonEditView.prototype.blurMoves = function(e) {
      var $input, $selectedMove, moveName, previousScrollPosition;
      $input = $(e.currentTarget);
      if (this._preventBlur) {
        previousScrollPosition = this.$el.scrollTop();
        $input.focus();
        e.preventDefault();
        this.$el.scrollTop(previousScrollPosition);
        return;
      }
      $selectedMove = this.$selectedMove();
      moveName = $selectedMove.data('move-id');
      this.filterMovesBy("");
      $(".table-moves .active").removeClass("active");
      if ($input.val().length === 0) {
        return this.recordMoves();
      } else {
        return this.insertMove($input, moveName);
      }
    };

    PokemonEditView.prototype.clickMoveName = function(e) {
      var $input, $moves, $this, moveName;
      $this = $(e.currentTarget);
      moveName = $this.data('move-id');
      $moves = this.$el.find('.selected_moves');
      $input = $moves.find('input:focus').first();
      if ($input.length === 0) {
        $input = $moves.find('input').first();
      }
      if ($input.length === 0) {
        return;
      }
      return this.insertMove($input, moveName);
    };

    PokemonEditView.prototype.insertMove = function($input, moveName) {
      var $firstInput, $moves, currentScrollPosition;
      currentScrollPosition = this.$el.scrollTop();
      this.preventBlurMoves();
      if (!this.buttonify($input, moveName)) {
        return;
      }
      $moves = this.$el.find('.selected_moves');
      $firstInput = $moves.find('input').first();
      if ($firstInput.length > 0) {
        $firstInput.focus();
        this.$el.scrollTop(currentScrollPosition);
      } else {
        this.$el.scrollTop(0);
      }
      return this.recordMoves();
    };

    PokemonEditView.prototype.recordMoves = function() {
      var $moves, movesArray;
      movesArray = [];
      $moves = this.$el.find('.selected_moves');
      $moves.find('.move-button').each(function() {
        var moveName;
        moveName = $(this).find("span").text().trim();
        if (moveName !== "") {
          return movesArray.push(moveName);
        }
      });
      return this.pokemon.set("moves", movesArray);
    };

    PokemonEditView.prototype.$selectedMove = function() {
      var $allMoves, $table;
      $table = this.$el.find('.table-moves');
      $allMoves = $table.find('tbody tr');
      return $allMoves.filter('.active').first();
    };

    PokemonEditView.prototype.clickSelectedMove = function(e) {
      var $input, $this, moveName;
      $this = $(e.currentTarget);
      moveName = $this.find('span').text();
      $input = $("<input type='text' value='" + moveName + "'/>");
      $this.replaceWith($input);
      $input.focus().select();
      return $(".table-moves tr[data-move-id='" + moveName + "']").addClass("active");
    };

    PokemonEditView.prototype.removeSelectedMove = function(e) {
      var $input, $this;
      $this = $(e.currentTarget).parent();
      $input = $("<input type='text'/>");
      $this.replaceWith($input);
      $input.focus();
      return e.stopPropagation();
    };

    PokemonEditView.prototype.buttonify = function($input, moveName) {
      var type;
      if (!(moveName in this.moveData)) {
        return false;
      }
      if ($input.is(":focus")) {
        this.filterMovesBy("");
        $(".table-moves .active").removeClass("active");
      }
      type = this.moveData[moveName].type.toLowerCase();
      $input.replaceWith("<div class=\"button move-button " + type + "\"><span>" + moveName + "</span><div class='close'>&times;</div></div>");
      return true;
    };

    PokemonEditView.prototype.keydownMoves = function(e) {
      var $activeMove, $allMoves, $input, $nextMove, $prevMove, $table;
      $input = $(e.currentTarget);
      $table = this.$el.find('.table-moves');
      $allMoves = $table.find('tbody tr');
      switch (e.which) {
        case 13:
          $activeMove = this.$selectedMove();
          return $activeMove.click();
        case 38:
          $activeMove = $allMoves.filter('.active').first();
          $prevMove = $activeMove.prevAll(":visible").first();
          if ($prevMove.length > 0) {
            $activeMove.removeClass('active');
            return $prevMove.addClass('active');
          }
          break;
        case 40:
          $activeMove = $allMoves.filter('.active').first();
          $nextMove = $activeMove.nextAll(":visible").first();
          if ($nextMove.length > 0) {
            $activeMove.removeClass('active');
            return $nextMove.addClass('active');
          }
          break;
        default:
          return _.defer((function(_this) {
            return function() {
              var moveName;
              if (!$input.is(":focus")) {
                return;
              }
              moveName = $input.val();
              return _this.filterMovesBy(moveName);
            };
          })(this));
      }
    };

    PokemonEditView.prototype.filterMovesBy = function(moveName) {
      var $allMoves, $moves, $table, moveRegex;
      moveName = moveName.replace(/\s+|-/g, "");
      $table = this.$el.find('.table-moves');
      $allMoves = $table.find('tbody tr');
      moveRegex = new RegExp(moveName, "i");
      $moves = $allMoves.filter(function() {
        var $move;
        $move = $(this);
        moveName = $move.data('move-search-id');
        return moveRegex.test(moveName);
      });
      $table.addClass('hidden');
      $moves.removeClass('hidden');
      $allMoves.not($moves).addClass('hidden');
      $allMoves.removeClass('active');
      $moves.first().addClass('active');
      return $table.removeClass('hidden');
    };

    PokemonEditView.prototype.disableEventsAndExecute = function(callback) {
      var isOutermost;
      isOutermost = !this._eventsDisabled;
      this._eventsDisabled = true;
      if (isOutermost) {
        this.undelegateEvents();
      }
      callback();
      if (isOutermost) {
        this.delegateEvents();
      }
      if (isOutermost) {
        return this._eventsDisabled = false;
      }
    };

    PokemonEditView.prototype.render = function() {
      this.$el.html(this.editTemplate({
        window: window,
        speciesList: this.speciesList,
        itemList: this.itemList
      }));
      attachSelectize(this.$el.find(".species_list"), {
        render: {
          option: (function(_this) {
            return function(item, escape) {
              var pbv, team, tier;
              team = _this.pokemon.getTeam();
              if (team.hasPBV()) {
                pbv = PokeBattle.PBV.determinePBV(_this.generation, {
                  species: item.value
                });
                return "<div class='clearfix'>" + item.text + "<div class='pbv'>" + pbv + "</div></div>";
              } else if (team.hasTier()) {
                tier = PokeBattle.Tier.determineTier(_this.generation, {
                  species: item.value
                });
                return "<div class='clearfix'>" + item.text + "<div class='tier'>" + tier.humanName + "</div></div>";
              }
            };
          })(this)
        }
      });
      attachSelectize(this.$el.find(".selected_item"));
      return this;
    };

    PokemonEditView.prototype.renderPokemon = function() {
      var $elements;
      this.renderSpecies();
      this.renderNonStats();
      this.renderStats();
      this.renderMoves();
      this.renderFormat();
      $elements = this.$el.find("input, select").not(".species input, .species select");
      $elements.prop("disabled", this.pokemon.isNull);
      setSelectizeDisabled($elements, this.pokemon.isNull);
      return this;
    };

    PokemonEditView.prototype.renderPBV = function() {
      var individualPBV, maxPBV, pbv, team;
      individualPBV = this.pokemon.getPBV();
      this.$(".individual-format").text(individualPBV);
      team = this.pokemon.getTeam();
      pbv = team.getPBV();
      maxPBV = team.getMaxPBV();
      this.$(".total-format").text(pbv).toggleClass("red", pbv > maxPBV);
      return this.$(".max-format").text(maxPBV);
    };

    PokemonEditView.prototype.renderTier = function() {
      var individualTier, maxTier, team, teamtier, tier;
      individualTier = this.pokemon.getTier();
      this.$('.individual-format').text(individualTier.humanName);
      team = this.pokemon.getTeam();
      if (team) {
        teamtier = team.getTier();
        tier = team.getTier();
        maxTier = team.getMaxTier();
        this.$(".total-format").text(teamtier.humanName).toggleClass("red", teamtier.tierRank > maxTier.tierRank);
        return this.$(".max-format").text(maxTier.humanName);
      }
    };

    PokemonEditView.prototype.renderFormat = function() {
      var team;
      team = this.pokemon.getTeam();
      if (team && team.hasPBV()) {
        return this.renderPBV();
      } else if (team && team.hasTier()) {
        return this.renderTier();
      }
    };

    PokemonEditView.prototype.renderSpecies = function() {
      return this.disableEventsAndExecute((function(_this) {
        return function() {
          var html;
          setSelectizeValue(_this.$(".species_list"), _this.pokemon.get("species"));
          html = _this.pokemon.isNull ? "" : _this.speciesTemplate({
            window: window,
            pokemon: _this.pokemon
          });
          _this.$(".species-info").html(html);
          _this.$(".selected_shininess").toggleClass("selected", _this.pokemon.get('shiny') === true);
          return _this.$(".selected_happiness").toggleClass("selected", _this.pokemon.get("happiness") === 0);
        };
      })(this));
    };

    PokemonEditView.prototype.getTeam = function() {
      return this.pokemon.getTeam();
    };

    PokemonEditView.prototype.renderNonStats = function() {
      var $nonStats, displayedGenders, populateSelect;
      $nonStats = this.$el.find(".non-stats");
      populateSelect = function(searchStr, valueTextPairs, selectedValue) {
        var $select, pair, text, value, _i, _len;
        $select = $nonStats.find(searchStr).empty();
        for (_i = 0, _len = valueTextPairs.length; _i < _len; _i++) {
          pair = valueTextPairs[_i];
          value = text = pair;
          if (pair instanceof Array) {
            value = pair[0];
            text = pair[1];
          }
          $select.append($("<option>").attr("value", value).text(text));
        }
        return $select.val(selectedValue);
      };
      displayedGenders = {
        F: "Female",
        M: "Male",
        Genderless: "Genderless"
      };
      return this.disableEventsAndExecute((function(_this) {
        return function() {
          var g, genders;
          genders = (function() {
            var _i, _len, _ref, _results;
            _ref = this.pokemon.getGenders();
            _results = [];
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
              g = _ref[_i];
              _results.push([g, displayedGenders[g]]);
            }
            return _results;
          }).call(_this);
          $nonStats.find(".selected_nickname").val(_this.pokemon.get("name"));
          populateSelect(".selected_ability", _this.pokemon.getAbilities(), _this.pokemon.get("ability"));
          populateSelect(".selected_nature", _this.pokemon.getNatures(), _this.pokemon.get("nature"));
          setSelectizeValue(_this.$(".selected_item"), _this.pokemon.get("item"));
          populateSelect(".selected_gender", genders, _this.pokemon.get("gender"));
          return $nonStats.find(".selected_level").val(_this.pokemon.get("level"));
        };
      })(this));
    };

    PokemonEditView.prototype.renderStats = function() {
      var pokemon, remainingEvs;
      pokemon = this.pokemon;
      this.$(".iv-entry").each(function() {
        var $input, stat;
        $input = $(this);
        stat = $input.data("stat");
        return $input.val(pokemon.iv(stat));
      });
      this.$(".ev-entry").each(function() {
        var $input, stat;
        if ($(this).is(":focus")) {
          return;
        }
        $input = $(this);
        stat = $input.data("stat");
        return $input.val(pokemon.ev(stat));
      });
      this.$('.base-stat').each(function() {
        var $this, stat;
        $this = $(this);
        stat = $this.data("stat");
        return $this.text(pokemon.base(stat));
      });
      this.$('.stat-total').each(function() {
        var $this, stat;
        $this = $(this);
        stat = $this.data("stat");
        $this.text(pokemon.stat(stat));
        $this.removeClass('plus-nature minus-nature');
        if (pokemon.natureBoost(stat) > 1) {
          $this.addClass('plus-nature');
          $this.text($this.text() + '+');
        }
        if (pokemon.natureBoost(stat) < 1) {
          $this.addClass('minus-nature');
          return $this.text($this.text() + '-');
        }
      });
      remainingEvs = 508 - this.pokemon.getTotalEVs();
      this.$('.remaining-evs-amount').text(remainingEvs).toggleClass("over-limit", remainingEvs < 0);
      return this.$('.select-hidden-power').val(this.pokemon.get('hiddenPowerType'));
    };

    PokemonEditView.prototype.renderMoves = function() {
      var $moveSection;
      $moveSection = this.$el.find(".moves-section");
      if (this.pokemon.isNull) {
        $moveSection.html("");
        return;
      }
      $moveSection.html(this.movesTemplate({
        window: window,
        pokemon: this.pokemon
      }));
      return $moveSection.find('.selected_moves input').each((function(_this) {
        return function(i, el) {
          var $this, moveName;
          $this = $(el);
          moveName = $this.val();
          return _this.buttonify($this, moveName);
        };
      })(this));
    };

    return PokemonEditView;

  })(Backbone.View);

}).call(this);

(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  this.TeambuilderView = (function(_super) {
    __extends(TeambuilderView, _super);

    function TeambuilderView() {
      this.renderSaved = __bind(this.renderSaved, this);
      this.renderSaving = __bind(this.renderSaving, this);
      this.validateImportedTeam = __bind(this.validateImportedTeam, this);
      this.renderImportTeamModal = __bind(this.renderImportTeamModal, this);
      this.renderFormat = __bind(this.renderFormat, this);
      this.renderTier = __bind(this.renderTier, this);
      this.renderPBV = __bind(this.renderPBV, this);
      this.renderPokemon = __bind(this.renderPokemon, this);
      this.renderPokemonList = __bind(this.renderPokemonList, this);
      this.renderTeam = __bind(this.renderTeam, this);
      this.renderTeams = __bind(this.renderTeams, this);
      this.render = __bind(this.render, this);
      this.resetHeaderButtons = __bind(this.resetHeaderButtons, this);
      this.dirty = __bind(this.dirty, this);
      this.goBackToOverview = __bind(this.goBackToOverview, this);
      this.keypressTeamName = __bind(this.keypressTeamName, this);
      this.blurTeamName = __bind(this.blurTeamName, this);
      this.getTeam = __bind(this.getTeam, this);
      this.getSelectedTeam = __bind(this.getSelectedTeam, this);
      this.getAllTeams = __bind(this.getAllTeams, this);
      this.setSelectedTeam = __bind(this.setSelectedTeam, this);
      this.getSelectedPokemon = __bind(this.getSelectedPokemon, this);
      this.setSelectedPokemonIndex = __bind(this.setSelectedPokemonIndex, this);
      this.changeTeamFormat = __bind(this.changeTeamFormat, this);
      this.saveTeam = __bind(this.saveTeam, this);
      this.addNewPokemon = __bind(this.addNewPokemon, this);
      this.addNewPokemonEvent = __bind(this.addNewPokemonEvent, this);
      this.exportTeam = __bind(this.exportTeam, this);
      this.changeTeamId = __bind(this.changeTeamId, this);
      this.changeTeam = __bind(this.changeTeam, this);
      this.deleteTeam = __bind(this.deleteTeam, this);
      this.deleteTeamEvent = __bind(this.deleteTeamEvent, this);
      this.cloneTeam = __bind(this.cloneTeam, this);
      this.resetTeams = __bind(this.resetTeams, this);
      this.addNewTeam = __bind(this.addNewTeam, this);
      this.addNewTeamEvent = __bind(this.addNewTeamEvent, this);
      this.addEmptyPokemon = __bind(this.addEmptyPokemon, this);
      this.attachEventsToTeam = __bind(this.attachEventsToTeam, this);
      this.clickPokemon = __bind(this.clickPokemon, this);
      this.clickTeam = __bind(this.clickTeam, this);
      this.initialize = __bind(this.initialize, this);
      return TeambuilderView.__super__.constructor.apply(this, arguments);
    }

    TeambuilderView.prototype.template = JST['teambuilder/main'];

    TeambuilderView.prototype.teamTemplate = JST['teambuilder/team'];

    TeambuilderView.prototype.teamsTemplate = JST['teambuilder/teams'];

    TeambuilderView.prototype.pokemonListTemplate = JST['teambuilder/pokemon_list'];

    TeambuilderView.prototype.events = {
      'click .add-new-team': 'addNewTeamEvent',
      'click .export-team': 'exportTeam',
      'click .clone-team': 'cloneTeam',
      'click .delete-team': 'deleteTeamEvent',
      'click .go-to-team': 'clickTeam',
      'click .import-team': 'renderImportTeamModal',
      'click .change-format-dropdown a': 'changeTeamFormat',
      'blur .team_name': 'blurTeamName',
      'keypress .team_name': 'keypressTeamName',
      'click .go_back': 'goBackToOverview',
      'click .pokemon_list li': 'clickPokemon',
      'click .add_pokemon': 'addNewPokemonEvent',
      'click .save_team': 'saveTeam'
    };

    TeambuilderView.prototype.initialize = function(attributes) {
      this.selectedPokemon = 0;
      this.selectedTeam = null;
      this.render();
      this.listenTo(PokeBattle.TeamStore, 'reset', this.resetTeams);
      this.listenTo(PokeBattle.TeamStore, 'add', this.addNewTeam);
      this.listenTo(PokeBattle.TeamStore, 'remove', this.deleteTeam);
      this.listenTo(PokeBattle.TeamStore, 'change:id', this.changeTeamId);
      this.listenTo(PokeBattle.TeamStore, 'reset', this.renderTeams);
      this.listenTo(PokeBattle.TeamStore, 'saving', this.renderSaving);
      this.listenTo(PokeBattle.TeamStore, 'saved', this.renderSaved);
      this.listenTo(PokeBattle.TeamStore, 'render', (function(_this) {
        return function(team) {
          _this.renderTeams();
          if (_this.getSelectedTeam() && team.id === _this.getSelectedTeam().id) {
            return _this.setSelectedTeam(team);
          }
        };
      })(this));
      return this.pokemonEditView = new PokemonEditView({
        el: this.$('.pokemon_edit'),
        onPokemonChange: (function(_this) {
          return function(newPokemon) {
            var team;
            team = _this.getSelectedTeam();
            team.replace(_this.selectedPokemon, newPokemon);
            return _this.renderTier();
          };
        })(this)
      });
    };

    TeambuilderView.prototype.clickTeam = function(e) {
      var $team, team;
      $team = $(e.currentTarget).closest('.select-team');
      team = PokeBattle.TeamStore.get($team.data('cid'));
      return this.setSelectedTeam(team);
    };

    TeambuilderView.prototype.clickPokemon = function(e) {
      var $listItem, index;
      $listItem = $(e.currentTarget);
      index = this.$('.pokemon_list li').index($listItem);
      return this.setSelectedPokemonIndex(index);
    };

    TeambuilderView.prototype.attachEventsToTeam = function(team) {
      if (team.attachedTeambuildEvents) {
        return;
      }
      this.listenTo(team, 'add:pokemon', this.renderPokemon);
      this.listenTo(team, 'change:pokemon[*].species change:pokemon[*].forme', (function(_this) {
        return function(pokemon) {
          _this.renderPokemonList();
          return _this.renderPokemon(pokemon);
        };
      })(this));
      this.listenTo(team, 'add:pokemon remove:pokemon', this.renderPokemonList);
      this.listenTo(team, 'reset:pokemon', ((function(_this) {
        return function() {
          return _this.changeTeam(team);
        };
      })(this)));
      this.listenTo(team, 'change nested-change reset:pokemon add:pokemon remove:pokemon', this.dirty);
      this.listenTo(team, 'change:pokemon[*] reset:pokemon add:pokemon remove:pokemon', this.renderTier, this.renderPBV);
      return team.attachedTeambuildEvents = true;
    };

    TeambuilderView.prototype.addEmptyPokemon = function(team) {
      return team.get('pokemon').add(new NullPokemon());
    };

    TeambuilderView.prototype.addNewTeamEvent = function(e) {
      var team;
      team = new Team();
      PokeBattle.TeamStore.add(team);
      return team.save();
    };

    TeambuilderView.prototype.addNewTeam = function(team) {
      while (team.get('pokemon').length < 6) {
        this.addEmptyPokemon(team);
      }
      this.$('.teambuilder_teams').append(this.teamTemplate({
        team: team,
        window: window
      }));
      return this.attachEventsToTeam(team);
    };

    TeambuilderView.prototype.resetTeams = function(teamStore) {
      return teamStore.forEach((function(_this) {
        return function(team) {
          return _this.attachEventsToTeam(team);
        };
      })(this));
    };

    TeambuilderView.prototype.cloneTeam = function(e) {
      var $team, cid, clone;
      $team = $(e.currentTarget).closest('.select-team');
      cid = $team.data('cid');
      clone = this.getTeam(cid).clone().set("id", null);
      PokeBattle.TeamStore.add(clone);
      clone.save();
      return false;
    };

    TeambuilderView.prototype.deleteTeamEvent = function(e) {
      var $team, team;
      if (!confirm("Do you really want to delete this team?")) {
        return false;
      }
      $team = $(e.currentTarget).closest('.select-team');
      team = this.getTeam($team.data('cid'));
      PokeBattle.TeamStore.remove(team);
      team.destroy();
      return false;
    };

    TeambuilderView.prototype.deleteTeam = function(team) {
      return this.$(".select-team[data-cid=" + team.cid + "]").remove();
    };

    TeambuilderView.prototype.changeTeam = function(team) {
      var html;
      html = $(this.teamTemplate({
        team: team,
        window: window
      })).html();
      return this.$(".select-team[data-cid=" + team.cid + "]").html(html);
    };

    TeambuilderView.prototype.changeTeamId = function(team) {
      return this.$(".select-team[data-cid=" + team.cid + "]").attr('data-id', team.id);
    };

    TeambuilderView.prototype.exportTeam = function(e) {
      var $modal, $team, id, teamJSON, teamString;
      $team = $(e.currentTarget).closest('.select-team');
      id = $team.data('id');
      if (!this.getTeam(id).hasNonNullPokemon()) {
        alert("You cannot export empty teams. Please add some pokemon first.");
        return false;
      }
      teamJSON = this.getTeam(id).toNonNullJSON();
      teamString = PokeBattle.exportTeam(teamJSON.pokemon);
      $modal = PokeBattle.modal('modals/export_team');
      $modal.find('.exported-team').val(teamString);
      $modal.find('textarea, input').first().focus().select();
      return false;
    };

    TeambuilderView.prototype.addNewPokemonEvent = function() {
      return this.addNewPokemon(this.getSelectedTeam());
    };

    TeambuilderView.prototype.addNewPokemon = function(team) {
      this.addEmptyPokemon(team);
      return this.$('.pokemon_list li').last().click();
    };

    TeambuilderView.prototype.saveTeam = function() {
      var clone, team;
      clone = this.getSelectedTeam();
      team = PokeBattle.TeamStore.get(clone.id);
      team.save(clone.toJSON(), {
        silent: true
      });
      return this.resetHeaderButtons();
    };

    TeambuilderView.prototype.changeTeamFormat = function(e) {
      var $link, format, realformat, team;
      $link = $(e.currentTarget);
      format = $link.data('format');
      team = this.getSelectedTeam();
      realformat = window.PokeBattle.conditions.Formats_[format];
      console.log(team.hasPBV());
      console.log(team.hasTier());
      if (realformat.tierBased && team.hasPBV()) {
        console.log('this');
      } else if (!realformat.tierBased && team.hasTier()) {
        console.log('that');
      }
      if (format !== team.get('generation')) {
        team.set('generation', format);
        this.renderTeam();
        return this.dirty();
      }
    };

    TeambuilderView.prototype.setSelectedPokemonIndex = function(index) {
      var pokemon;
      pokemon = this.getSelectedTeam().at(index);
      this.selectedPokemon = index;
      this.pokemonEditView.setPokemon(pokemon);
      this.renderPokemon(pokemon);
      this.$(".navigation li").removeClass("active");
      return this.$(".navigation li").eq(index).addClass("active");
    };

    TeambuilderView.prototype.getSelectedPokemon = function() {
      return this.getSelectedTeam().at(this.selectedPokemon);
    };

    TeambuilderView.prototype.setSelectedTeam = function(team) {
      this.selectedTeam = team.clone();
      this.selectedTeam.id = team.id;
      this.selectedTeam.cid = team.cid;
      this.selectedPokemon = 0;
      this.attachEventsToTeam(this.selectedTeam);
      return this.renderTeam();
    };

    TeambuilderView.prototype.getAllTeams = function() {
      return PokeBattle.TeamStore.models;
    };

    TeambuilderView.prototype.getSelectedTeam = function() {
      return this.selectedTeam;
    };

    TeambuilderView.prototype.getTeam = function(idx) {
      return PokeBattle.TeamStore.get(idx);
    };

    TeambuilderView.prototype.blurTeamName = function() {
      var teamName;
      teamName = this.$('.team_name').text();
      return this.getSelectedTeam().set('name', teamName);
    };

    TeambuilderView.prototype.keypressTeamName = function(e) {
      if (e.which === 13) {
        return this.$('.team_name').blur();
      }
    };

    TeambuilderView.prototype.goBackToOverview = function() {
      return this.renderTeams();
    };

    TeambuilderView.prototype.dirty = function() {
      this.$('.go_back').text('Discard changes');
      return this.$('.save_team').removeClass('disabled');
    };

    TeambuilderView.prototype.resetHeaderButtons = function() {
      this.$('.go_back').text('Back');
      return this.$('.save_team').addClass('disabled');
    };

    TeambuilderView.prototype.render = function() {
      this.$el.html(this.template({
        pokemon: this.getSelectedTeam(),
        selected: this.selectedPokemon,
        window: window
      }));
      return this.renderTeams();
    };

    TeambuilderView.prototype.renderTeams = function() {
      this.$('.display_teams').html(this.teamsTemplate({
        teams: this.getAllTeams(),
        window: window
      }));
      this.$('.display_teams').removeClass('hidden');
      this.$('.display_pokemon').addClass('hidden');
      return this;
    };

    TeambuilderView.prototype.renderTeam = function() {
      var team;
      team = this.getSelectedTeam();
      this.pokemonEditView.setFormat(team.get('generation') || DEFAULT_FORMAT);
      this.resetHeaderButtons();
      this.renderFormat();
      this.renderPokemonList();
      this.setSelectedPokemonIndex(this.selectedPokemon);
      this.$('.team_name').text(team.getName());
      this.$('.display_teams').addClass('hidden');
      return this.$('.display_pokemon').removeClass('hidden');
    };

    TeambuilderView.prototype.renderPokemonList = function() {
      var $pokemon_list, team;
      team = this.getSelectedTeam();
      $pokemon_list = this.$(".pokemon_list").empty();
      $pokemon_list.html(this.pokemonListTemplate({
        window: window,
        pokemonList: team.get('pokemon').models
      }));
      $pokemon_list.find("li[data-pokemon-index=" + this.selectedPokemon + "]").addClass("active");
      if (team.length < 6) {
        return this.$(".add_pokemon").show();
      } else {
        return this.$(".add_pokemon").hide();
      }
    };

    TeambuilderView.prototype.renderPokemon = function(pokemon) {
      return this.pokemonEditView.setPokemon(pokemon);
    };

    TeambuilderView.prototype.renderPBV = function(pokemon) {
      var $listItem, individualPBV, totalPBV;
      if (pokemon) {
        individualPBV = pokemon.getPBV();
        $listItem = this.$(".pokemon_list li[data-pokemon-cid=" + pokemon.cid + "]");
        $listItem.find(".pbv-value").text(individualPBV);
      }
      totalPBV = this.getSelectedTeam().getPBV();
      this.pokemonEditView.setTeamPBV(totalPBV);
      return this.pokemonEditView.renderPBV();
    };

    TeambuilderView.prototype.renderTier = function(pokemon) {
      var individualTier, totalTier;
      if (pokemon) {
        individualTier = pokemon.getTier();
      }
      totalTier = this.getSelectedTeam().getTier();
      this.pokemonEditView.setTeamTier(totalTier);
      return this.pokemonEditView.renderTier();
    };

    TeambuilderView.prototype.renderFormat = function() {
      var allformats, format, text;
      allformats = window.PokeBattle.conditions.Formats();
      format = this.getSelectedTeam().get("generation");
      if (!(format in allformats)) {
        format = DEFAULT_FORMAT;
      }
      text = this.$(".change-format-dropdown a[data-format='" + format + "']").text();
      return this.$(".current-format").text(text);
    };

    TeambuilderView.prototype.renderImportTeamModal = function() {
      var $modal;
      $modal = PokeBattle.modal('modals/import_team', (function(_this) {
        return function($modal) {
          return $modal.on('click', '.import-team-submit', function(e) {
            var $errors, errors, listErrors, pokemonJSON, team, teamString;
            teamString = $modal.find('.imported-team').val();
            pokemonJSON = PokeBattle.parseTeam(teamString);
            errors = _this.validateImportedTeam(pokemonJSON);
            if (errors.length > 0) {
              listErrors = errors.map(function(e) {
                return "<li>" + e + "</li>";
              }).join('');
              $errors = $modal.find('.form-errors');
              $errors.html("<ul>" + listErrors + "</ul>").removeClass('hidden');
            } else {
              team = new Team({
                pokemon: pokemonJSON,
                teambuilder: true
              });
              PokeBattle.TeamStore.add(team);
              team.save();
              $modal.find('.imported-team').val("");
              $modal.modal('hide');
            }
            return false;
          });
        };
      })(this));
      return $modal.find('.imported-team').first().focus();
    };

    TeambuilderView.prototype.validateImportedTeam = function(json) {
      var SpeciesData, errors, pokemon, pokemonSpecies;
      errors = [];
      pokemonSpecies = (function() {
        var _i, _len, _results;
        _results = [];
        for (_i = 0, _len = json.length; _i < _len; _i++) {
          pokemon = json[_i];
          _results.push(pokemon.species);
        }
        return _results;
      })();
      SpeciesData = window.Generations[DEFAULT_GENERATION.toUpperCase()].SpeciesData;
      pokemonSpecies = pokemonSpecies.filter(function(s) {
        return !(s in SpeciesData);
      });
      if (pokemonSpecies.length > 0) {
        errors.push.apply(errors, pokemonSpecies.map(function(n) {
          return "" + n + " is not a valid Pokemon.";
        }));
        return errors;
      }
      return errors;
    };

    TeambuilderView.prototype.renderSaving = function(team) {
      var $team;
      $team = $(".select-team[data-cid='" + team.cid + "']");
      return $team.find('.show_spinner').removeClass('hidden');
    };

    TeambuilderView.prototype.renderSaved = function(team) {
      var $team;
      $team = $(".select-team[data-cid='" + team.cid + "']");
      return $team.find('.show_spinner').addClass('hidden');
    };

    return TeambuilderView;

  })(Backbone.View);

}).call(this);

(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  this.BattleListView = (function(_super) {
    __extends(BattleListView, _super);

    function BattleListView() {
      this.render = __bind(this.render, this);
      this.refreshList = __bind(this.refreshList, this);
      this.initialize = __bind(this.initialize, this);
      return BattleListView.__super__.constructor.apply(this, arguments);
    }

    BattleListView.prototype.template = JST['battle_list'];

    BattleListView.prototype.initialize = function(attributes) {
      this.battles = [];
      return this.render();
    };

    BattleListView.prototype.refreshList = function() {
      return PokeBattle.primus.send("getBattleList", (function(_this) {
        return function(battles) {
          _this.battles = _(battles).sortBy(function(battle) {
            return battle[3];
          });
          return _this.render();
        };
      })(this));
    };

    BattleListView.prototype.render = function() {
      return this.$el.html(this.template({
        battles: this.battles
      }));
    };

    return BattleListView;

  })(Backbone.View);

}).call(this);

(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  this.PrivateMessagesView = (function(_super) {
    __extends(PrivateMessagesView, _super);

    function PrivateMessagesView() {
      this.focusPopupEvent = __bind(this.focusPopupEvent, this);
      this.challengeCanceledEvent = __bind(this.challengeCanceledEvent, this);
      this.sendChallengeEvent = __bind(this.sendChallengeEvent, this);
      this.toggleChallengeEvent = __bind(this.toggleChallengeEvent, this);
      this.focusChatEvent = __bind(this.focusChatEvent, this);
      this.closePopupEvent = __bind(this.closePopupEvent, this);
      this.minimizePopupEvent = __bind(this.minimizePopupEvent, this);
      this.keyUpEvent = __bind(this.keyUpEvent, this);
      this.keyPressEvent = __bind(this.keyPressEvent, this);
      this.createChallenge = __bind(this.createChallenge, this);
      this.messageFromPopup = __bind(this.messageFromPopup, this);
      this.$closestPopup = __bind(this.$closestPopup, this);
      this.$findOrCreatePopup = __bind(this.$findOrCreatePopup, this);
      this.$findPopup = __bind(this.$findPopup, this);
      this.repositionPopups = __bind(this.repositionPopups, this);
      this.positionPopup = __bind(this.positionPopup, this);
      this.scrollToBottom = __bind(this.scrollToBottom, this);
      this.isAtBottom = __bind(this.isAtBottom, this);
      this.isOpen = __bind(this.isOpen, this);
      this.notifyLeave = __bind(this.notifyLeave, this);
      this.notifyJoin = __bind(this.notifyJoin, this);
      this.resetNotifications = __bind(this.resetNotifications, this);
      this.closeChallenge = __bind(this.closeChallenge, this);
      this.cancelChallenge = __bind(this.cancelChallenge, this);
      this.openChallenge = __bind(this.openChallenge, this);
      this.receiveMessage = __bind(this.receiveMessage, this);
      this.addLogMessages = __bind(this.addLogMessages, this);
      this.addMessage = __bind(this.addMessage, this);
      this.showPopup = __bind(this.showPopup, this);
      this.minimizePopup = __bind(this.minimizePopup, this);
      this.closePopup = __bind(this.closePopup, this);
      this.focusPopup = __bind(this.focusPopup, this);
      this.createPopup = __bind(this.createPopup, this);
      this.initialize = __bind(this.initialize, this);
      return PrivateMessagesView.__super__.constructor.apply(this, arguments);
    }

    PrivateMessagesView.prototype.messageTemplate = JST['private_message'];

    PrivateMessagesView.prototype.events = {
      "keypress .chat_input": "keyPressEvent",
      "keyup .chat_input": "keyUpEvent",
      "click .challenge_button, .cancel_challenge": "toggleChallengeEvent",
      "click .popup_messages": "focusChatEvent",
      "click .title_minimize": "minimizePopupEvent",
      "click .title_close": "closePopupEvent",
      "challenge .popup": "sendChallengeEvent",
      "cancelChallenge .popup": "challengeCanceledEvent",
      "focus .popup": "focusPopupEvent"
    };

    PrivateMessagesView.prototype.initialize = function() {
      this.listenTo(this.collection, 'open', this.createPopup);
      this.listenTo(this.collection, 'focus', this.focusPopup);
      this.listenTo(this.collection, 'receive', this.receiveMessage);
      this.listenTo(this.collection, 'close', this.closePopup);
      this.listenTo(this.collection, 'minimize', this.minimizePopup);
      this.listenTo(this.collection, 'show', this.showPopup);
      this.listenTo(this.collection, 'openChallenge', this.openChallenge);
      this.listenTo(this.collection, 'cancelChallenge', this.cancelChallenge);
      this.listenTo(this.collection, 'closeChallenge', this.closeChallenge);
      return this.listenTo(this.collection, 'focus show', this.resetNotifications);
    };

    PrivateMessagesView.prototype.createPopup = function(message) {
      var $html, id, title;
      title = id = message.id;
      $html = this.$findPopup(id);
      if (this.$findPopup(id).length === 0) {
        $html = $(this.messageTemplate({
          window: window,
          id: id,
          title: title
        }));
        this.$el.append($html);
        this.positionPopup($html, this.$(".popup:visible").length - 1);
        this.addLogMessages($html, message.getLog());
      }
      return $html;
    };

    PrivateMessagesView.prototype.focusPopup = function(message) {
      var $popup, id;
      id = message.id;
      $popup = this.$findPopup(id);
      return $popup.find('.chat_input').focus();
    };

    PrivateMessagesView.prototype.closePopup = function(message) {
      var username;
      username = message.id;
      this.$findPopup(username).remove();
      return this.repositionPopups();
    };

    PrivateMessagesView.prototype.minimizePopup = function(message) {
      var $popup, username;
      username = message.id;
      $popup = this.$findPopup(username);
      $popup.addClass('hidden');
      return this.repositionPopups();
    };

    PrivateMessagesView.prototype.showPopup = function(message) {
      var $popup, username;
      username = message.id;
      $popup = this.$findPopup(username);
      this.$el.append($popup);
      $popup.removeClass('hidden');
      this.scrollToBottom($popup);
      return this.repositionPopups();
    };

    PrivateMessagesView.prototype.addMessage = function($popup, message) {
      var $messages;
      $messages = $popup.find('.popup_messages');
      return $messages.append(message);
    };

    PrivateMessagesView.prototype.addLogMessages = function($popup, log) {
      var message, messageHtml, opts, username, _i, _len, _ref, _ref1;
      messageHtml = "";
      for (_i = 0, _len = log.length; _i < _len; _i++) {
        _ref = log[_i], username = _ref.username, message = _ref.message, opts = _ref.opts;
        message = _.escape(message);
        if (username === PokeBattle.username) {
          username = "Me";
        }
        if ((_ref1 = opts.type) === 'error' || _ref1 === 'alert') {
          messageHtml += "<p class='grey'>" + message + "</p>";
        } else {
          messageHtml += "<p class='grey'><strong>" + username + ":</strong> " + message + "</p>";
        }
      }
      this.addMessage($popup, messageHtml);
      return this.scrollToBottom($popup);
    };

    PrivateMessagesView.prototype.receiveMessage = function(messageModel, messageId, username, message, options) {
      var $popup, wasAtBottom;
      message = _.escape(message);
      $popup = this.$findOrCreatePopup(messageId);
      wasAtBottom = this.isAtBottom($popup);
      if (username === PokeBattle.username) {
        username = "Me";
      }
      if (options.type === 'error') {
        this.addMessage($popup, "<p class='red italic'>" + message + "</p>");
      } else if (options.type === 'alert') {
        this.addMessage($popup, "<p class='yellow italic'>" + message + "</p>");
      } else {
        if (username !== "Me" && !$popup.find('.chat_input').is(":focus")) {
          $popup.addClass('new_message');
          PokeBattle.notifyUser(PokeBattle.NotificationTypes.PRIVATE_MESSAGE, username);
        } else {
          this.resetNotifications(messageModel);
        }
        this.addMessage($popup, "<p><strong>" + username + ":</strong> " + message + "</p>");
      }
      if (wasAtBottom) {
        return this.scrollToBottom($popup);
      }
    };

    PrivateMessagesView.prototype.openChallenge = function(messageId, generation, conditions) {
      var $challenge, $popup;
      $popup = this.$findOrCreatePopup(messageId);
      $challenge = this.createChallenge($popup, generation, conditions);
      if (generation) {
        $challenge.find('.is_not_challenger').addClass('hidden');
        return $challenge.find('.is_challenger').removeClass('hidden');
      }
    };

    PrivateMessagesView.prototype.cancelChallenge = function(messageId) {
      var $challenge, $popup;
      $popup = this.$findOrCreatePopup(messageId);
      $challenge = $popup.find('.challenge');
      $challenge.find('.icon-spinner').addClass('hidden');
      $challenge.find('.send_challenge, .select').removeClass('disabled');
      $challenge.find('.challenge_text').text("Challenge");
      return $challenge.find(".cancel_challenge").text('Close');
    };

    PrivateMessagesView.prototype.closeChallenge = function(messageId) {
      var $challenge, $popup;
      $popup = this.$findOrCreatePopup(messageId);
      $challenge = $popup.find('.challenge');
      $challenge.addClass('hidden');
      return $popup.find('.popup_messages').removeClass('small');
    };

    PrivateMessagesView.prototype.resetNotifications = function(message) {
      return message.set('notifications', 0);
    };

    PrivateMessagesView.prototype.notifyJoin = function(user) {
      var message;
      message = this.collection.get(user.id);
      if (!this.isOpen(message)) {
        return;
      }
      return message != null ? message.add(user.id, "" + user.id + " is now online!", {
        type: "alert"
      }) : void 0;
    };

    PrivateMessagesView.prototype.notifyLeave = function(user) {
      var message;
      message = this.collection.get(user.id);
      if (!this.isOpen(message)) {
        return;
      }
      return message != null ? message.add(user.id, "" + user.id + " is now offline.", {
        type: "alert"
      }) : void 0;
    };

    PrivateMessagesView.prototype.isOpen = function(message) {
      return message && this.$findPopup(message.id).length > 0;
    };

    PrivateMessagesView.prototype.isAtBottom = function($popup) {
      var $el;
      $el = $popup.find('.popup_messages');
      return $el[0].scrollHeight - $el.scrollTop() <= $el.outerHeight();
    };

    PrivateMessagesView.prototype.scrollToBottom = function($popup) {
      var messages;
      messages = $popup.find('.popup_messages')[0];
      if (!messages) {
        return;
      }
      messages.scrollTop = messages.scrollHeight;
      return false;
    };

    PrivateMessagesView.prototype.positionPopup = function($popup, index) {
      var leftOffset;
      leftOffset = $('#content').position().left;
      return $popup.css({
        left: leftOffset + index * $popup.outerWidth(true)
      });
    };

    PrivateMessagesView.prototype.repositionPopups = function() {
      return this.$(".popup:visible").each((function(_this) {
        return function(index, self) {
          return _this.positionPopup($(self), index);
        };
      })(this));
    };

    PrivateMessagesView.prototype.$findPopup = function(id) {
      return this.$(".popup[data-user-id='" + id + "']");
    };

    PrivateMessagesView.prototype.$findOrCreatePopup = function(messageId) {
      var $popup;
      $popup = this.$findPopup(messageId);
      if ($popup.length === 0) {
        $popup = this.createPopup(this.collection.get(messageId));
      }
      return $popup;
    };

    PrivateMessagesView.prototype.$closestPopup = function(target) {
      var $target;
      $target = $(target);
      if ($target.hasClass("popup")) {
        return $target;
      }
      return $target.closest(".popup");
    };

    PrivateMessagesView.prototype.messageFromPopup = function(target) {
      var $popup, message;
      $popup = this.$closestPopup(target);
      message = this.collection.get($popup.data('user-id'));
      return message;
    };

    PrivateMessagesView.prototype.createChallenge = function($popup, generation, conditions) {
      var $challenge;
      $challenge = $popup.find('.challenge');
      $challenge.html(JST['challenge']());
      createChallengePane({
        eventName: "challenge",
        button: $popup.find('.send_challenge'),
        acceptButton: $popup.find('.accept_challenge'),
        rejectButton: $popup.find('.reject_challenge'),
        populate: $popup.find(".challenge_data"),
        generation: generation,
        personId: $popup.data('user-id'),
        defaultClauses: conditions || [Conditions.TEAM_PREVIEW, Conditions.PBV_1000, Conditions.SLEEP_CLAUSE, Conditions.EVASION_CLAUSE, Conditions.SPECIES_CLAUSE, Conditions.OHKO_CLAUSE, Conditions.PRANKSTER_SWAGGER_CLAUSE, Conditions.UNRELEASED_BAN],
        blockedClauses: (conditions != null) || [Conditions.RATED_BATTLE]
      });
      $popup.find('.popup_messages').addClass('small');
      $challenge.removeClass('hidden');
      return $challenge;
    };

    PrivateMessagesView.prototype.keyPressEvent = function(e) {
      var $input, message, text;
      switch (e.which) {
        case 13:
          $input = $(e.currentTarget);
          message = this.messageFromPopup(e.currentTarget);
          text = $input.val();
          if (text.length === 0) {
            return;
          }
          PokeBattle.primus.send('privateMessage', message.id, text);
          return $input.val('');
      }
    };

    PrivateMessagesView.prototype.keyUpEvent = function(e) {
      switch (e.which) {
        case 27:
          return this.closePopupEvent(e);
      }
    };

    PrivateMessagesView.prototype.minimizePopupEvent = function(e) {
      var message;
      message = this.messageFromPopup(e.currentTarget);
      return message.trigger('minimize', message);
    };

    PrivateMessagesView.prototype.closePopupEvent = function(e) {
      var message;
      message = this.messageFromPopup(e.currentTarget);
      return message.trigger('close', message);
    };

    PrivateMessagesView.prototype.focusChatEvent = function(e) {
      return this.$closestPopup(e.currentTarget).find('input').focus();
    };

    PrivateMessagesView.prototype.toggleChallengeEvent = function(e) {
      var $challenge, $popup, wasAtBottom;
      $popup = this.$closestPopup(e.currentTarget);
      $challenge = $popup.find('.challenge');
      wasAtBottom = this.isAtBottom($popup);
      if ($challenge.hasClass("hidden")) {
        this.createChallenge($popup);
      } else if ($challenge.find('.cancel_challenge').text() === 'Cancel') {
        $popup.find('.send_challenge').click();
      } else {
        this.closeChallenge(this.messageFromPopup($popup));
      }
      if (wasAtBottom) {
        return this.scrollToBottom($popup);
      }
    };

    PrivateMessagesView.prototype.sendChallengeEvent = function(e) {
      var $challenge, $popup;
      $popup = this.$closestPopup(e.currentTarget);
      $challenge = $popup.find('.challenge');
      $challenge.find(".icon-spinner").removeClass('hidden');
      $challenge.find(".challenge_text").text('Challenging...');
      return $challenge.find(".cancel_challenge").text('Cancel');
    };

    PrivateMessagesView.prototype.challengeCanceledEvent = function(e) {
      var message;
      message = this.messageFromPopup(e.currentTarget);
      return message.trigger('cancelChallenge', message.id);
    };

    PrivateMessagesView.prototype.focusPopupEvent = function(e) {
      var $popup;
      $popup = this.$closestPopup(e.currentTarget);
      $popup.removeClass('new_message');
      return this.resetNotifications(this.collection.get($popup.data('user-id')));
    };

    return PrivateMessagesView;

  })(Backbone.View);

}).call(this);

(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  this.SidebarView = (function(_super) {
    __extends(SidebarView, _super);

    function SidebarView() {
      this.resetNotifications = __bind(this.resetNotifications, this);
      this.changeWindowToBattle = __bind(this.changeWindowToBattle, this);
      this.changeWindowTo = __bind(this.changeWindowTo, this);
      this.focusMessageEvent = __bind(this.focusMessageEvent, this);
      this.focusRoomEvent = __bind(this.focusRoomEvent, this);
      this.focusLobbyEvent = __bind(this.focusLobbyEvent, this);
      this.focusBattleEvent = __bind(this.focusBattleEvent, this);
      this.closeMessageEvent = __bind(this.closeMessageEvent, this);
      this.leaveRoomEvent = __bind(this.leaveRoomEvent, this);
      this.focusLobby = __bind(this.focusLobby, this);
      this.renderMessageNotifications = __bind(this.renderMessageNotifications, this);
      this.resetMessages = __bind(this.resetMessages, this);
      this.removeMessage = __bind(this.removeMessage, this);
      this.addMessage = __bind(this.addMessage, this);
      this.resetBattles = __bind(this.resetBattles, this);
      this.removeBattle = __bind(this.removeBattle, this);
      this.addBattle = __bind(this.addBattle, this);
      this.renderNotifications = __bind(this.renderNotifications, this);
      this.render = __bind(this.render, this);
      this.showBattleList = __bind(this.showBattleList, this);
      this.showTeambuilder = __bind(this.showTeambuilder, this);
      this.initialize = __bind(this.initialize, this);
      return SidebarView.__super__.constructor.apply(this, arguments);
    }

    SidebarView.prototype.template = JST['navigation'];

    SidebarView.prototype.events = {
      "click .logo": "focusLobbyEvent",
      "click .nav_rooms li": 'focusRoomEvent',
      "click .nav_battles li": 'focusBattleEvent',
      "click .nav_messages li": 'focusMessageEvent',
      "click .nav_battles .close": 'leaveRoomEvent',
      "click .nav_messages .close": 'closeMessageEvent',
      "click .nav_teambuilder": 'showTeambuilder',
      "click .nav_battle_list": 'showBattleList'
    };

    SidebarView.prototype.initialize = function(attributes) {
      this.currentWindow = null;
      this.listenTo(PokeBattle.battles, 'add', this.addBattle);
      this.listenTo(PokeBattle.battles, 'remove', this.removeBattle);
      this.listenTo(PokeBattle.battles, 'reset', this.resetBattles);
      this.listenTo(PokeBattle.battles, 'change:notifications', this.renderNotifications);
      this.listenTo(PokeBattle.messages, 'open receive', this.addMessage);
      this.listenTo(PokeBattle.messages, 'close', this.removeMessage);
      this.listenTo(PokeBattle.messages, 'reset', this.resetMessages);
      this.listenTo(PokeBattle.messages, 'change:notifications', this.renderMessageNotifications);
      return this.render();
    };

    SidebarView.prototype.showTeambuilder = function() {
      return this.changeWindowTo($("#teambuilder-section"), $(".nav_teambuilder"));
    };

    SidebarView.prototype.showBattleList = function() {
      this.changeWindowTo($("#battle-list-section"), $(".nav_battle_list"));
      return PokeBattle.battleList.refreshList();
    };

    SidebarView.prototype.render = function() {
      return this.$el.html(this.template({
        battles: PokeBattle.battles
      }));
    };

    SidebarView.prototype.renderNotifications = function(battle) {
      var $notifications, notificationCount;
      $notifications = this.$("[data-battle-id='" + battle.id + "'] .notifications");
      if (this.currentWindow.data('battle-id') === battle.id) {
        battle.set('notifications', 0, {
          silent: true
        });
        $notifications.addClass('hidden');
        return;
      }
      notificationCount = battle.get('notifications');
      if (notificationCount > 0) {
        $notifications.text(notificationCount);
        return $notifications.removeClass('hidden');
      } else {
        return $notifications.addClass('hidden');
      }
    };

    SidebarView.prototype.addBattle = function(battle) {
      var $li;
      this.$(".header_battles, .nav_battles").removeClass("hidden");
      $li = $("<li class=\"nav_item fake_link\" data-battle-id=\"" + battle.id + "\">\n<div class=\"nav_meta\">\n  <div class=\"notifications hidden\">0</div>\n  <div class=\"close\">&times;</div>\n</div>" + (battle.get('playerIds').join(' VS ')) + "</li>");
      $li.appendTo(this.$('.nav_battles'));
      return $li.click();
    };

    SidebarView.prototype.removeBattle = function(battle) {
      var $battle, $navItems, $next, index;
      $navItems = this.$(".nav_item");
      $battle = this.$(".nav_item[data-battle-id='" + battle.id + "']");
      index = $navItems.index($battle);
      $battle.remove();
      if (PokeBattle.battles.size() === 0) {
        this.$(".header_battles, .nav_battles").addClass('hidden');
        return PokeBattle.navigation.focusLobby();
      } else {
        $next = $navItems.eq(index).add($navItems.eq(index - 1));
        return $next.first().click();
      }
    };

    SidebarView.prototype.resetBattles = function(battles) {
      var battle, _i, _len, _results;
      _results = [];
      for (_i = 0, _len = battles.length; _i < _len; _i++) {
        battle = battles[_i];
        _results.push(this.addBattle(battle));
      }
      return _results;
    };

    SidebarView.prototype.addMessage = function(message) {
      var $li;
      if (this.$(".nav_item[data-message-id='" + message.id + "']").length) {
        return;
      }
      this.$(".header_messages, .nav_messages").removeClass("hidden");
      $li = $("<li class=\"nav_item fake_link\" data-message-id=\"" + message.id + "\">\n<div class=\"nav_meta\">\n  <div class=\"notifications hidden\">0</div>\n  <div class=\"close\">&times;</div>\n</div>" + message.id + "</li>");
      $li.appendTo(this.$('.nav_messages'));
      return this.renderMessageNotifications(message);
    };

    SidebarView.prototype.removeMessage = function(message) {
      this.$(".nav_item[data-message-id='" + message.id + "']").remove();
      if (this.$('.nav_messages li').length === 0) {
        return this.$(".header_messages").addClass("hidden");
      }
    };

    SidebarView.prototype.resetMessages = function(messages) {
      var message, _i, _len, _results;
      _results = [];
      for (_i = 0, _len = messages.length; _i < _len; _i++) {
        message = messages[_i];
        _results.push(this.addMessage(message));
      }
      return _results;
    };

    SidebarView.prototype.renderMessageNotifications = function(message) {
      var $notifications, notificationCount;
      $notifications = this.$("[data-message-id='" + message.id + "'] .notifications");
      notificationCount = message.get('notifications');
      if (notificationCount > 0) {
        $notifications.text(notificationCount);
        return $notifications.removeClass('hidden');
      } else {
        return $notifications.addClass('hidden');
      }
    };

    SidebarView.prototype.focusLobby = function() {
      var $lobbyLink, $room;
      $lobbyLink = this.$(".nav_rooms li").first();
      this.resetNotifications($lobbyLink);
      $room = $('.chat_window');
      this.changeWindowTo($room, $lobbyLink);
      return PokeBattle.router.navigate("");
    };

    SidebarView.prototype.leaveRoomEvent = function(e) {
      var $navItem, battle, battleId;
      $navItem = $(e.currentTarget).closest('.nav_item');
      battleId = $navItem.data('battle-id');
      battle = PokeBattle.battles.get(battleId);
      if (battle.isPlaying()) {
        if (!confirm("Are you sure you want to forfeit this battle?")) {
          return;
        }
        battle.forfeit();
      }
      PokeBattle.battles.remove(battle);
      return false;
    };

    SidebarView.prototype.closeMessageEvent = function(e) {
      var $navItem, message, messageId;
      $navItem = $(e.currentTarget).closest('.nav_item');
      messageId = $navItem.data('message-id');
      message = PokeBattle.messages.get(messageId);
      return message.trigger('close', message);
    };

    SidebarView.prototype.focusBattleEvent = function(e) {
      var $this, battleId;
      $this = $(e.currentTarget);
      this.resetNotifications($this);
      battleId = $this.data('battle-id');
      return this.changeWindowToBattle(battleId);
    };

    SidebarView.prototype.focusLobbyEvent = function(e) {
      return this.focusLobby();
    };

    SidebarView.prototype.focusRoomEvent = function(e) {
      var $room, $this;
      $this = $(e.currentTarget);
      this.resetNotifications($this);
      $room = $('.chat_window');
      this.changeWindowTo($room, $this);
      return PokeBattle.router.navigate("");
    };

    SidebarView.prototype.focusMessageEvent = function(e) {
      var $navItem, message, messageId;
      $navItem = $(e.currentTarget).closest('.nav_item');
      messageId = $navItem.data('message-id');
      message = PokeBattle.messages.get(messageId);
      message.trigger('show', message);
      return message.trigger('focus', message);
    };

    SidebarView.prototype.changeWindowTo = function($toSelector, $navItem) {
      var $mainContent;
      $mainContent = $('#main-section');
      $mainContent.children().addClass("hidden");
      this.currentWindow = $toSelector.first();
      this.currentWindow.removeClass("hidden");
      this.currentWindow.find('.chat').trigger('scroll_to_bottom');
      this.$('.nav_item').removeClass('active');
      return $navItem.addClass('active');
    };

    SidebarView.prototype.changeWindowToBattle = function(battleId) {
      var $battle, $navItem;
      $battle = $(".battle_window[data-battle-id='" + battleId + "']");
      $navItem = this.$("[data-battle-id='" + battleId + "']");
      this.changeWindowTo($battle, $navItem);
      return PokeBattle.router.navigate("battles/" + battleId);
    };

    SidebarView.prototype.resetNotifications = function($link) {
      var battle, battleId;
      $link = $link.first();
      if ($link[0].tagName !== 'li') {
        $link = $link.closest('li');
      }
      if (battleId = $link.data('battle-id')) {
        battle = PokeBattle.battles.get(battleId);
        return battle.set('notifications', 0);
      }
    };

    return SidebarView;

  })(Backbone.View);

}).call(this);

(function() {
  if (PokeBattle.autoConnect === false) {
    return;
  }

  PokeBattle.primus = Primus.connect();

  PokeBattle.primus.on('listChatroom', function(id, users) {
    var room;
    if (room = PokeBattle.rooms.get({
      id: id
    })) {
      return room.get('users').reset(users);
    } else {
      room = PokeBattle.rooms.add({
        id: id,
        users: users
      });
      return new ChatView({
        model: room,
        el: $('#chat-section .chat')
      }).render();
    }
  });

  PokeBattle.primus.on('userMessage', function(id, username, data) {
    var room;
    room = PokeBattle.rooms.get(id);
    return room.userMessage(username, data);
  });

  PokeBattle.primus.on('rawMessage', function(id, message) {
    var room;
    room = PokeBattle.rooms.get(id);
    return room.rawMessage(message);
  });

  PokeBattle.primus.on('announce', function(id, klass, message) {
    var room;
    room = PokeBattle.rooms.get(id);
    return room.announce(klass, message);
  });

  PokeBattle.primus.on('joinChatroom', function(id, user) {
    var room;
    room = PokeBattle.rooms.get(id);
    return room.get('users').add(user);
  });

  PokeBattle.primus.on('leaveChatroom', function(id, user) {
    var room;
    room = PokeBattle.rooms.get(id);
    return room.get('users').remove(user);
  });

  PokeBattle.primus.on('topic', function(topic) {
    var room;
    room = PokeBattle.rooms.get("Lobby");
    return room.setTopic(topic);
  });

  PokeBattle.userList = new UserList();

  PokeBattle.battles = new BattleCollection([]);

  PokeBattle.messages = new PrivateMessages([]);

  PokeBattle.rooms = new Rooms([]);

  $(function() {
    PokeBattle.navigation = new SidebarView({
      el: $('#navigation')
    });
    PokeBattle.teambuilder = new TeambuilderView({
      el: $("#teambuilder-section")
    });
    PokeBattle.battleList = new BattleListView({
      el: $("#battle-list-section")
    });
    return new PrivateMessagesView({
      el: $("#messages"),
      collection: PokeBattle.messages
    });
  });

}).call(this);

(function() {
  var __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  this.challengePaneArray = [];

  this.challengePaneObject = (function() {
    function challengePaneObject(object) {
      this.object = object;
      this.event = this.object.eventName;
      this.button = this.object.button;
      this.populate = this.object.populate;
      this.clauses = this.object.defaultClauses;
      this.blockedClauses = this.object.blockedClauses;
    }

    return challengePaneObject;

  })();

  this.createChallengePane = function(opts) {
    var $PaneArray, $accept, $button, $buttons, $checkboxes, $format, $reject, $selectFormat, $wrapper, acceptEventName, altCreatedEvent, blockedClauses, cancelChallenge, cancelEventName, capitalizedEventName, defaultClauses, disableButtons, enableButtons, eventName, generation, getSelectedTeam, isAttachedToDom, personId, rejectEventName, renderCurrentTeam, selectedAlt, selectedTeamId, teamUpdated, toggleAltInput, _ref;
    $wrapper = opts.populate;
    $button = opts.button;
    $accept = opts.acceptButton || $();
    $reject = opts.rejectButton || $();
    $buttons = $button.add($accept).add($reject);
    eventName = opts.eventName;
    capitalizedEventName = "" + (eventName[0].toUpperCase()) + (eventName.substr(1));
    acceptEventName = "accept" + capitalizedEventName;
    rejectEventName = "reject" + capitalizedEventName;
    cancelEventName = "cancel" + capitalizedEventName;
    generation = opts.generation;
    personId = opts.personId;
    defaultClauses = opts.defaultClauses || [];
    blockedClauses = (_ref = opts.blockedClauses) != null ? _ref : false;
    selectedTeamId = null;
    selectedAlt = null;
    $PaneArray = this.challengePaneArray;
    getSelectedTeam = function() {
      return PokeBattle.TeamStore.get(selectedTeamId) || PokeBattle.TeamStore.at(0);
    };
    renderCurrentTeam = function($context) {
      var $selectTeam, currentTeam, html;
      $selectTeam = $context.find('.select-team');
      if (PokeBattle.TeamStore.length > 0) {
        currentTeam = getSelectedTeam();
        html = JST['team_dropdown']({
          window: window,
          team: currentTeam
        });
        return $selectTeam.html(html);
      } else {
        return $selectTeam.html("You have no teams!");
      }
    };
    cancelChallenge = function() {
      var format;
      enableButtons();
      if (personId) {
        PokeBattle.primus.send(cancelEventName, personId);
      } else {
        format = $selectFormat.data('format');
        PokeBattle.primus.send(cancelEventName, format);
      }
      return $button.trigger('cancelChallenge');
    };
    disableButtons = function() {
      $wrapper.find('.select').addClass('disabled');
      return $buttons.addClass('disabled');
    };
    enableButtons = function() {
      return $buttons.removeClass('disabled');
    };
    toggleAltInput = function(visible) {
      $wrapper.find('.alt-input').toggleClass("hidden", !visible);
      $wrapper.find('.alt-dropdown-section').toggleClass("hidden", visible);
      if (visible) {
        return $wrapper.find('.alt-input input').focus();
      }
    };
    isAttachedToDom = function() {
      return $.contains(document, $wrapper.get(0));
    };
    altCreatedEvent = function() {
      if (!isAttachedToDom()) {
        return PokeBattle.primus.off('altCreated', altCreatedEvent);
      }
      $wrapper.find('.alt-input input').val("");
      return toggleAltInput(false);
    };
    PokeBattle.primus.on('altCreated', altCreatedEvent);
    enableButtons();
    $wrapper.html(JST['new_battle']({
      window: window,
      defaultClauses: defaultClauses
    }));
    $selectFormat = $wrapper.find(".select-format");
    $button.on('click.challenge', function() {
      var $clauses, clauses, format, team, teamJSON, thisChallenge;
      thisChallenge = _.find($PaneArray, function(butt) {
        return butt.button.selector === $button.selector;
      });
      PokeBattle.requestNotifyPermission();
      format = $selectFormat.data('format');
      if (typeof format === "undefined" && typeof personId === "undefined") {
        format = $('.select-format').data('format');
      }
      if (!$button.hasClass('disabled')) {
        team = getSelectedTeam();
        if (!team) {
          alert("You need to create a team using the Teambuilder before you can battle.");
          PokeBattle.navigation.showTeambuilder();
          return;
        }
        disableButtons();
        teamJSON = team.toNonNullJSON().pokemon;
        if (personId) {
          $clauses = $wrapper.find('input:checked[type="checkbox"]');
          clauses = [];
          $clauses.each(function() {
            return clauses.push(parseInt($(this).val(), 10));
          });
          PokeBattle.primus.send(eventName, personId, format, teamJSON, thisChallenge.clauses, selectedAlt);
        } else {
          PokeBattle.primus.send(eventName, format, teamJSON, selectedAlt);
        }
        return $button.addClass('disabled').trigger('challenge');
      } else {
        return cancelChallenge();
      }
    });
    $accept.on('click.challenge', function() {
      var team, teamJSON;
      if ($(this).hasClass('disabled')) {
        return;
      }
      team = getSelectedTeam();
      if (!team) {
        alert("You need to create a team using the Teambuilder before you can battle.");
        PokeBattle.navigation.showTeambuilder();
        return;
      }
      disableButtons();
      teamJSON = team.toNonNullJSON().pokemon;
      return PokeBattle.primus.send(acceptEventName, personId, teamJSON, selectedAlt);
    });
    $reject.on('click.challenge', function() {
      if ($(this).hasClass('disabled')) {
        return;
      }
      disableButtons();
      return PokeBattle.primus.send(rejectEventName, personId);
    });
    $wrapper.find('.select-alt').click(function(e) {
      var html;
      html = JST['alt_dropdown']({
        alts: PokeBattle.alts.list,
        username: PokeBattle.username
      });
      return $wrapper.find('.alt-dropdown').html(html);
    });
    $wrapper.find('.alt-dropdown').on('click', '.select-alt-dropdown-item', function(e) {
      selectedAlt = $(this).data('alt-name');
      return $wrapper.find('.select-alt').html($(this).html());
    });
    $wrapper.find('.alt-dropdown').on('click', '.add-alt-dropdown-item', function(e) {
      return toggleAltInput(true);
    });
    $wrapper.find('.alt-input .add-button').click(function(e) {
      var altName;
      altName = $wrapper.find('.alt-input input').val().trim();
      return PokeBattle.alts.createAlt(altName);
    });
    $wrapper.find('.alt-input .cancel-button').click(function(e) {
      return toggleAltInput(false);
    });
    $wrapper.find('.select-team').click(function(e) {
      var allTeams, html;
      allTeams = PokeBattle.TeamStore.models || [];
      html = JST['team_dropdown']({
        window: window,
        teams: allTeams
      });
      return $wrapper.find('.team-dropdown').html(html);
    });
    $wrapper.find('.team-dropdown').on('click', '.select-team-dropdown-item', function(e) {
      var slot;
      slot = $(e.currentTarget).data('slot');
      selectedTeamId = PokeBattle.TeamStore.at(slot).id;
      return renderCurrentTeam($wrapper);
    });
    $wrapper.find('.team-dropdown').on('click', '.build-team-option', function(e) {
      return PokeBattle.navigation.showTeambuilder();
    });
    $wrapper.find('.format-dropdown').on('click', '.select-format-dropdown-item', function(e) {
      var $target, format;
      $target = $(e.currentTarget);
      format = $target.data('format');
      $selectFormat.text($target.text());
      return $selectFormat.data('format', format);
    });
    $wrapper.find('.select-alt').html(JST['alt_dropdown']({
      alt: null,
      username: PokeBattle.username
    }));
    if (generation) {
      $format = $wrapper.find(".format-dropdown a[data-format='" + generation + "']");
      $format.first().click();
      $wrapper.find('.select-format').addClass('disabled');
    } else {
      $wrapper.find('.format-dropdown a').first().click();
    }
    if (blockedClauses) {
      $checkboxes = $wrapper.find('input[type="checkbox"]');
      if (blockedClauses !== true) {
        $checkboxes = $checkboxes.filter(function() {
          var clause;
          clause = Number($(this).data('clause'));
          return __indexOf.call(blockedClauses, clause) >= 0;
        });
      }
      $checkboxes.prop('disabled', true);
      $checkboxes.closest('label').addClass('disabled');
    }
    renderCurrentTeam($wrapper);
    teamUpdated = function() {
      if (!isAttachedToDom()) {
        PokeBattle.TeamStore.off('add remove reset saved', teamUpdated);
        return;
      }
      return renderCurrentTeam($wrapper);
    };
    return PokeBattle.TeamStore.on('add remove reset saved', teamUpdated);
  };

}).call(this);

(function() {
  var NON_DEFAULT_FORMES_OFFSET, SpriteIds, generation, maxSpeciesId, n, p,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  this.PokemonIconBackground = function(species, forme) {
    var id, imgloc, imgname, pokemon, shiny, _ref;
    if (!(typeof species === "string")) {
      pokemon = species;
      id = ((_ref = pokemon.getSpecies()) != null ? _ref.id : void 0) || 0;
      forme = pokemon.forme || (typeof pokemon.get === "function" ? pokemon.get("forme") : void 0);
      shiny = pokemon.get('shiny');
    }
    id = id.toString();
    if (id.length === 1) {
      id = "00" + id;
    } else if (id.length === 2) {
      id = "0" + id;
    }
    imgname = "icon" + id;
    if (shiny === true) {
      imgname += "s";
    }
    if (forme && forme !== 'default') {
      imgname += "-" + forme;
    }
    imgloc = "../Sprites/Icons/" + imgname + ".png";
    return "background:url(" + imgloc + ")!important; background-size: cover!important;";
  };

  this.PokemonSprite = function(id, forme, options) {
    var front, kind, pokemon, shiny, _ref, _ref1, _ref2;
    if (options == null) {
      options = {};
    }
    if (id instanceof Pokemon) {
      pokemon = id;
      id = ((_ref = pokemon.getSpecies()) != null ? _ref.id : void 0) || 0;
      forme = pokemon.get('forme');
      options = {
        shiny: pokemon.get('shiny')
      };
    }
    front = (_ref1 = options.front) != null ? _ref1 : true;
    shiny = (_ref2 = options.shiny) != null ? _ref2 : false;
    kind = (front ? "front" : "back");
    if (shiny) {
      kind += "-s";
    }
    id = ("000" + id).substr(-3);
    if (forme && forme !== 'default') {
      id += "-" + forme;
    }
    return "../Sprites/" + kind + "/" + id + ".png";
  };

  this.TypeSprite = function(type) {
    return "../Sprites/types/" + (type.toLowerCase()) + ".png";
  };

  this.CategorySprite = function(type) {
    return "../Sprites/types/" + (type.toLowerCase()) + ".png";
  };

  this.TargetSprite = function(move) {
    var target;
    target = move.target;
    if (__indexOf.call(move["flags"], "distance") >= 0 && target === "selected-pokemon") {
      target = "distance";
    }
    return "//media.pokebattle.com/img/targets/" + (target.toLowerCase()) + ".png";
  };

  this.AchievementSprite = function(achievement) {
    return "//media.pokebattle.com/achievements/" + achievement.medium_image;
  };

  generation = Generations[DEFAULT_GENERATION.toUpperCase()];

  maxSpeciesId = Math.max.apply(Math, (function() {
    var _ref, _results;
    _ref = generation.SpeciesData;
    _results = [];
    for (n in _ref) {
      p = _ref[n];
      _results.push(p.id);
    }
    return _results;
  })());

  NON_DEFAULT_FORMES_OFFSET = maxSpeciesId + (16 - ((maxSpeciesId + 1) % 16));

  SpriteIds = {
    "Delta Bulbasaur": {
      "default": 727
    },
    "Abomasnow": {
      "default": 460,
      "mega": NON_DEFAULT_FORMES_OFFSET + 142
    },
    "Abra": {
      "default": 63
    },
    "Absol": {
      "default": 359,
      "mega": NON_DEFAULT_FORMES_OFFSET + 137
    },
    "Accelgor": {
      "default": 617
    },
    "Aerodactyl": {
      "default": 142,
      "mega": NON_DEFAULT_FORMES_OFFSET + 122
    },
    "Aggron": {
      "default": 306,
      "mega": NON_DEFAULT_FORMES_OFFSET + 133
    },
    "Aipom": {
      "default": 190
    },
    "Alakazam": {
      "default": 65,
      "mega": NON_DEFAULT_FORMES_OFFSET + 117
    },
    "Alomomola": {
      "default": 594
    },
    "Altaria": {
      "default": 334
    },
    "Ambipom": {
      "default": 424
    },
    "Amoonguss": {
      "default": 591
    },
    "Ampharos": {
      "default": 181,
      "mega": NON_DEFAULT_FORMES_OFFSET + 125
    },
    "Anorith": {
      "default": 347
    },
    "Arbok": {
      "default": 24
    },
    "Arcanine": {
      "default": 59
    },
    "Arceus": {
      "default": 493
    },
    "Archen": {
      "default": 566
    },
    "Archeops": {
      "default": 567
    },
    "Ariados": {
      "default": 168
    },
    "Armaldo": {
      "default": 348
    },
    "Aron": {
      "default": 304
    },
    "Articuno": {
      "default": 144
    },
    "Audino": {
      "default": 531
    },
    "Axew": {
      "default": 610
    },
    "Azelf": {
      "default": 482
    },
    "Azumarill": {
      "default": 184
    },
    "Azurill": {
      "default": 298
    },
    "Bagon": {
      "default": 371
    },
    "Baltoy": {
      "default": 343
    },
    "Banette": {
      "default": 354,
      "mega": NON_DEFAULT_FORMES_OFFSET + 136
    },
    "Barboach": {
      "default": 339
    },
    "Basculin": {
      "default": 550,
      "blue-striped": NON_DEFAULT_FORMES_OFFSET + 78
    },
    "Bastiodon": {
      "default": 411
    },
    "Bayleef": {
      "default": 153
    },
    "Beartic": {
      "default": 614
    },
    "Beautifly": {
      "default": 267
    },
    "Beedrill": {
      "default": 15
    },
    "Beheeyem": {
      "default": 606
    },
    "Beldum": {
      "default": 374
    },
    "Bellossom": {
      "default": 182
    },
    "Bellsprout": {
      "default": 69
    },
    "Bibarel": {
      "default": 400
    },
    "Bidoof": {
      "default": 399
    },
    "Bisharp": {
      "default": 625
    },
    "Blastoise": {
      "default": 9,
      "mega": NON_DEFAULT_FORMES_OFFSET + 116
    },
    "Blaziken": {
      "default": 257,
      "mega": NON_DEFAULT_FORMES_OFFSET + 130
    },
    "Blissey": {
      "default": 242
    },
    "Blitzle": {
      "default": 522
    },
    "Boldore": {
      "default": 525
    },
    "Bonsly": {
      "default": 438
    },
    "Bouffalant": {
      "default": 626
    },
    "Braviary": {
      "default": 628
    },
    "Breloom": {
      "default": 286
    },
    "Bronzong": {
      "default": 437
    },
    "Bronzor": {
      "default": 436
    },
    "Budew": {
      "default": 406
    },
    "Buizel": {
      "default": 418
    },
    "Bulbasaur": {
      "default": 1
    },
    "Buneary": {
      "default": 427
    },
    "Burmy": {
      "default": 412,
      "sandy": NON_DEFAULT_FORMES_OFFSET + 9,
      "trash": NON_DEFAULT_FORMES_OFFSET + 10
    },
    "Butterfree": {
      "default": 12
    },
    "Cacnea": {
      "default": 331
    },
    "Cacturne": {
      "default": 332
    },
    "Camerupt": {
      "default": 323
    },
    "Carnivine": {
      "default": 455
    },
    "Carracosta": {
      "default": 565
    },
    "Carvanha": {
      "default": 318
    },
    "Cascoon": {
      "default": 268
    },
    "Castform": {
      "default": 351,
      "rainy": 49,
      "snowy": 50,
      "sunny": 51
    },
    "Caterpie": {
      "default": 10
    },
    "Celebi": {
      "default": 251
    },
    "Chandelure": {
      "default": 609
    },
    "Chansey": {
      "default": 113
    },
    "Charizard": {
      "default": 6,
      "mega-x": NON_DEFAULT_FORMES_OFFSET + 114,
      "mega-y": NON_DEFAULT_FORMES_OFFSET + 115
    },
    "Charmander": {
      "default": 4
    },
    "Charmeleon": {
      "default": 5
    },
    "Chatot": {
      "default": 441
    },
    "Cherrim": {
      "default": 421
    },
    "Cherubi": {
      "default": 420
    },
    "Chikorita": {
      "default": 152
    },
    "Chimchar": {
      "default": 390
    },
    "Chimecho": {
      "default": 358
    },
    "Chinchou": {
      "default": 170
    },
    "Chingling": {
      "default": 433
    },
    "Cinccino": {
      "default": 573
    },
    "Clamperl": {
      "default": 366
    },
    "Claydol": {
      "default": 344
    },
    "Clefable": {
      "default": 36
    },
    "Clefairy": {
      "default": 35
    },
    "Cleffa": {
      "default": 173
    },
    "Cloyster": {
      "default": 91
    },
    "Cobalion": {
      "default": 638
    },
    "Cofagrigus": {
      "default": 563
    },
    "Combee": {
      "default": 415
    },
    "Combusken": {
      "default": 256
    },
    "Conkeldurr": {
      "default": 534
    },
    "Corphish": {
      "default": 341
    },
    "Corsola": {
      "default": 222
    },
    "Cottonee": {
      "default": 546
    },
    "Cradily": {
      "default": 346
    },
    "Cranidos": {
      "default": 408
    },
    "Crawdaunt": {
      "default": 342
    },
    "Cresselia": {
      "default": 488
    },
    "Croagunk": {
      "default": 453
    },
    "Crobat": {
      "default": 169
    },
    "Croconaw": {
      "default": 159
    },
    "Crustle": {
      "default": 558
    },
    "Cryogonal": {
      "default": 615
    },
    "Cubchoo": {
      "default": 613
    },
    "Cubone": {
      "default": 104
    },
    "Cyndaquil": {
      "default": 155
    },
    "Darkrai": {
      "default": 491
    },
    "Darmanitan": {
      "default": 555,
      "zen": NON_DEFAULT_FORMES_OFFSET + 81
    },
    "Darumaka": {
      "default": 554
    },
    "Deerling": {
      "default": 585
    },
    "Deino": {
      "default": 633
    },
    "Delcatty": {
      "default": 301
    },
    "Delibird": {
      "default": 225
    },
    "Deoxys": {
      "default": 386,
      "attack": NON_DEFAULT_FORMES_OFFSET + 52,
      "defense": NON_DEFAULT_FORMES_OFFSET + 53,
      "speed": NON_DEFAULT_FORMES_OFFSET + 55
    },
    "Dewgong": {
      "default": 87
    },
    "Dewott": {
      "default": 502
    },
    "Dialga": {
      "default": 483
    },
    "Diglett": {
      "default": 50
    },
    "Ditto": {
      "default": 132
    },
    "Dodrio": {
      "default": 85
    },
    "Doduo": {
      "default": 84
    },
    "Donphan": {
      "default": 232
    },
    "Dragonair": {
      "default": 148
    },
    "Dragonite": {
      "default": 149
    },
    "Drapion": {
      "default": 452
    },
    "Dratini": {
      "default": 147
    },
    "Drifblim": {
      "default": 426
    },
    "Drifloon": {
      "default": 425
    },
    "Drilbur": {
      "default": 529
    },
    "Drowzee": {
      "default": 96
    },
    "Druddigon": {
      "default": 621
    },
    "Ducklett": {
      "default": 580
    },
    "Dugtrio": {
      "default": 51
    },
    "Dunsparce": {
      "default": 206
    },
    "Duosion": {
      "default": 578
    },
    "Durant": {
      "default": 632
    },
    "Dusclops": {
      "default": 356
    },
    "Dusknoir": {
      "default": 477
    },
    "Duskull": {
      "default": 355
    },
    "Dustox": {
      "default": 269
    },
    "Dwebble": {
      "default": 557
    },
    "Eelektrik": {
      "default": 603
    },
    "Eelektross": {
      "default": 604
    },
    "Eevee": {
      "default": 133
    },
    "Ekans": {
      "default": 23
    },
    "Electabuzz": {
      "default": 125
    },
    "Electivire": {
      "default": 466
    },
    "Electrike": {
      "default": 309
    },
    "Electrode": {
      "default": 101
    },
    "Elekid": {
      "default": 239
    },
    "Elgyem": {
      "default": 605
    },
    "Emboar": {
      "default": 500
    },
    "Emolga": {
      "default": 587
    },
    "Empoleon": {
      "default": 395
    },
    "Entei": {
      "default": 244
    },
    "Escavalier": {
      "default": 589
    },
    "Espeon": {
      "default": 196
    },
    "Excadrill": {
      "default": 530
    },
    "Exeggcute": {
      "default": 102
    },
    "Exeggutor": {
      "default": 103
    },
    "Exploud": {
      "default": 295
    },
    "Farfetch'd": {
      "default": 83
    },
    "Fearow": {
      "default": 22
    },
    "Feebas": {
      "default": 349
    },
    "Feraligatr": {
      "default": 160
    },
    "Ferroseed": {
      "default": 597
    },
    "Ferrothorn": {
      "default": 598
    },
    "Finneon": {
      "default": 456
    },
    "Flaaffy": {
      "default": 180
    },
    "Flareon": {
      "default": 136
    },
    "Floatzel": {
      "default": 419
    },
    "Flygon": {
      "default": 330
    },
    "Foongus": {
      "default": 590
    },
    "Forretress": {
      "default": 205
    },
    "Fraxure": {
      "default": 611
    },
    "Frillish": {
      "default": 592
    },
    "Froslass": {
      "default": 478
    },
    "Furret": {
      "default": 162
    },
    "Gabite": {
      "default": 444
    },
    "Gallade": {
      "default": 475
    },
    "Galvantula": {
      "default": 596
    },
    "Garbodor": {
      "default": 569
    },
    "Garchomp": {
      "default": 445,
      "mega": NON_DEFAULT_FORMES_OFFSET + 140
    },
    "Gardevoir": {
      "default": 282,
      "mega": NON_DEFAULT_FORMES_OFFSET + 131
    },
    "Gastly": {
      "default": 92
    },
    "Gastrodon": {
      "default": 423
    },
    "Genesect": {
      "default": 649
    },
    "Gengar": {
      "default": 94,
      "mega": NON_DEFAULT_FORMES_OFFSET + 118
    },
    "Geodude": {
      "default": 74
    },
    "Gible": {
      "default": 443
    },
    "Gigalith": {
      "default": 526
    },
    "Girafarig": {
      "default": 203
    },
    "Giratina": {
      "default": 487,
      "origin": NON_DEFAULT_FORMES_OFFSET + 74
    },
    "Glaceon": {
      "default": 471
    },
    "Glalie": {
      "default": 362
    },
    "Glameow": {
      "default": 431
    },
    "Gligar": {
      "default": 207
    },
    "Gliscor": {
      "default": 472
    },
    "Gloom": {
      "default": 44
    },
    "Golbat": {
      "default": 42
    },
    "Goldeen": {
      "default": 118
    },
    "Golduck": {
      "default": 55
    },
    "Golem": {
      "default": 76
    },
    "Golett": {
      "default": 622
    },
    "Golurk": {
      "default": 623
    },
    "Gorebyss": {
      "default": 368
    },
    "Gothita": {
      "default": 574
    },
    "Gothitelle": {
      "default": 576
    },
    "Gothorita": {
      "default": 575
    },
    "Granbull": {
      "default": 210
    },
    "Graveler": {
      "default": 75
    },
    "Grimer": {
      "default": 88
    },
    "Grotle": {
      "default": 388
    },
    "Groudon": {
      "default": 383
    },
    "Grovyle": {
      "default": 253
    },
    "Growlithe": {
      "default": 58
    },
    "Grumpig": {
      "default": 326
    },
    "Gulpin": {
      "default": 316
    },
    "Gurdurr": {
      "default": 533
    },
    "Gyarados": {
      "default": 130,
      "mega": NON_DEFAULT_FORMES_OFFSET + 121
    },
    "Happiny": {
      "default": 440
    },
    "Hariyama": {
      "default": 297
    },
    "Haunter": {
      "default": 93
    },
    "Haxorus": {
      "default": 612
    },
    "Heatmor": {
      "default": 631
    },
    "Heatran": {
      "default": 485
    },
    "Heracross": {
      "default": 214,
      "mega": NON_DEFAULT_FORMES_OFFSET + 127
    },
    "Herdier": {
      "default": 507
    },
    "Hippopotas": {
      "default": 449
    },
    "Hippowdon": {
      "default": 450
    },
    "Hitmonchan": {
      "default": 107
    },
    "Hitmonlee": {
      "default": 106
    },
    "Hitmontop": {
      "default": 237
    },
    "Ho-Oh": {
      "default": 250
    },
    "Honchkrow": {
      "default": 430
    },
    "Hoothoot": {
      "default": 163
    },
    "Hoppip": {
      "default": 187
    },
    "Horsea": {
      "default": 116
    },
    "Houndoom": {
      "default": 229,
      "mega": NON_DEFAULT_FORMES_OFFSET + 128
    },
    "Houndour": {
      "default": 228
    },
    "Huntail": {
      "default": 367
    },
    "Hydreigon": {
      "default": 635
    },
    "Hypno": {
      "default": 97
    },
    "Igglybuff": {
      "default": 174
    },
    "Illumise": {
      "default": 314
    },
    "Infernape": {
      "default": 392
    },
    "Ivysaur": {
      "default": 2
    },
    "Jellicent": {
      "default": 593
    },
    "Jigglypuff": {
      "default": 39
    },
    "Jirachi": {
      "default": 385
    },
    "Jolteon": {
      "default": 135
    },
    "Joltik": {
      "default": 595
    },
    "Jumpluff": {
      "default": 189
    },
    "Jynx": {
      "default": 124
    },
    "Kabuto": {
      "default": 140
    },
    "Kabutops": {
      "default": 141
    },
    "Kadabra": {
      "default": 64
    },
    "Kakuna": {
      "default": 14
    },
    "Kangaskhan": {
      "default": 115,
      "mega": NON_DEFAULT_FORMES_OFFSET + 119
    },
    "Karrablast": {
      "default": 588
    },
    "Kecleon": {
      "default": 352
    },
    "Keldeo": {
      "default": 647,
      "resolute": NON_DEFAULT_FORMES_OFFSET + 103
    },
    "Kingdra": {
      "default": 230
    },
    "Kingler": {
      "default": 99
    },
    "Kirlia": {
      "default": 281
    },
    "Klang": {
      "default": 600
    },
    "Klink": {
      "default": 599
    },
    "Klinklang": {
      "default": 601
    },
    "Koffing": {
      "default": 109
    },
    "Krabby": {
      "default": 98
    },
    "Kricketot": {
      "default": 401
    },
    "Kricketune": {
      "default": 402
    },
    "Krokorok": {
      "default": 552
    },
    "Krookodile": {
      "default": 553
    },
    "Kyogre": {
      "default": 382
    },
    "Kyurem": {
      "default": 646,
      "black": NON_DEFAULT_FORMES_OFFSET + 101,
      "white": NON_DEFAULT_FORMES_OFFSET + 102
    },
    "Lairon": {
      "default": 305
    },
    "Lampent": {
      "default": 608
    },
    "Landorus": {
      "default": 645,
      "therian": NON_DEFAULT_FORMES_OFFSET + 100
    },
    "Lanturn": {
      "default": 171
    },
    "Lapras": {
      "default": 131
    },
    "Larvesta": {
      "default": 636
    },
    "Larvitar": {
      "default": 246
    },
    "Latias": {
      "default": 380,
      "mega": NON_DEFAULT_FORMES_OFFSET + 138
    },
    "Latios": {
      "default": 381,
      "mega": NON_DEFAULT_FORMES_OFFSET + 139
    },
    "Leafeon": {
      "default": 470
    },
    "Leavanny": {
      "default": 542
    },
    "Ledian": {
      "default": 166
    },
    "Ledyba": {
      "default": 165
    },
    "Lickilicky": {
      "default": 463
    },
    "Lickitung": {
      "default": 108
    },
    "Liepard": {
      "default": 510
    },
    "Lileep": {
      "default": 345
    },
    "Lilligant": {
      "default": 549
    },
    "Lillipup": {
      "default": 506
    },
    "Linoone": {
      "default": 264
    },
    "Litwick": {
      "default": 607
    },
    "Lombre": {
      "default": 271
    },
    "Lopunny": {
      "default": 428
    },
    "Lotad": {
      "default": 270
    },
    "Loudred": {
      "default": 294
    },
    "Lucario": {
      "default": 448,
      "mega": NON_DEFAULT_FORMES_OFFSET + 141
    },
    "Ludicolo": {
      "default": 272
    },
    "Lugia": {
      "default": 249
    },
    "Lumineon": {
      "default": 457
    },
    "Lunatone": {
      "default": 337
    },
    "Luvdisc": {
      "default": 370
    },
    "Luxio": {
      "default": 404
    },
    "Luxray": {
      "default": 405
    },
    "Machamp": {
      "default": 68
    },
    "Machoke": {
      "default": 67
    },
    "Machop": {
      "default": 66
    },
    "Magby": {
      "default": 240
    },
    "Magcargo": {
      "default": 219
    },
    "Magikarp": {
      "default": 129
    },
    "Magmar": {
      "default": 126
    },
    "Magmortar": {
      "default": 467
    },
    "Magnemite": {
      "default": 81
    },
    "Magneton": {
      "default": 82
    },
    "Magnezone": {
      "default": 462
    },
    "Makuhita": {
      "default": 296
    },
    "Mamoswine": {
      "default": 473
    },
    "Manaphy": {
      "default": 490
    },
    "Mandibuzz": {
      "default": 630
    },
    "Manectric": {
      "default": 310,
      "mega": NON_DEFAULT_FORMES_OFFSET + 135
    },
    "Mankey": {
      "default": 56
    },
    "Mantine": {
      "default": 226
    },
    "Mantyke": {
      "default": 458
    },
    "Maractus": {
      "default": 556
    },
    "Mareep": {
      "default": 179
    },
    "Marill": {
      "default": 183
    },
    "Marowak": {
      "default": 105
    },
    "Marshtomp": {
      "default": 259
    },
    "Masquerain": {
      "default": 284
    },
    "Mawile": {
      "default": 303,
      "mega": NON_DEFAULT_FORMES_OFFSET + 132
    },
    "Medicham": {
      "default": 308,
      "mega": NON_DEFAULT_FORMES_OFFSET + 134
    },
    "Meditite": {
      "default": 307
    },
    "Meganium": {
      "default": 154
    },
    "Meloetta": {
      "default": 648,
      "pirouette": NON_DEFAULT_FORMES_OFFSET + 93
    },
    "Meowth": {
      "default": 52
    },
    "Mesprit": {
      "default": 481
    },
    "Metagross": {
      "default": 376
    },
    "Metang": {
      "default": 375
    },
    "Metapod": {
      "default": 11
    },
    "Mew": {
      "default": 151
    },
    "Mewtwo": {
      "default": 150,
      "mega-x": NON_DEFAULT_FORMES_OFFSET + 123,
      "mega-y": NON_DEFAULT_FORMES_OFFSET + 124
    },
    "Mienfoo": {
      "default": 619
    },
    "Mienshao": {
      "default": 620
    },
    "Mightyena": {
      "default": 262
    },
    "Milotic": {
      "default": 350
    },
    "Miltank": {
      "default": 241
    },
    "Mime Jr.": {
      "default": 439
    },
    "Minccino": {
      "default": 572
    },
    "Minun": {
      "default": 312
    },
    "Misdreavus": {
      "default": 200
    },
    "Mismagius": {
      "default": 429
    },
    "Moltres": {
      "default": 146
    },
    "Monferno": {
      "default": 391
    },
    "Mothim": {
      "default": 414
    },
    "Mr. Mime": {
      "default": 122
    },
    "Mudkip": {
      "default": 258
    },
    "Muk": {
      "default": 89
    },
    "Munchlax": {
      "default": 446
    },
    "Munna": {
      "default": 517
    },
    "Murkrow": {
      "default": 198
    },
    "Musharna": {
      "default": 518
    },
    "Natu": {
      "default": 177
    },
    "Nidoking": {
      "default": 34
    },
    "Nidoqueen": {
      "default": 31
    },
    "Nidoran♀": {
      "default": 29
    },
    "Nidoran♂": {
      "default": 32
    },
    "Nidorina": {
      "default": 30
    },
    "Nidorino": {
      "default": 33
    },
    "Nincada": {
      "default": 290
    },
    "Ninetales": {
      "default": 38
    },
    "Ninjask": {
      "default": 291
    },
    "Noctowl": {
      "default": 164
    },
    "Nosepass": {
      "default": 299
    },
    "Numel": {
      "default": 322
    },
    "Nuzleaf": {
      "default": 274
    },
    "Octillery": {
      "default": 224
    },
    "Oddish": {
      "default": 43
    },
    "Omanyte": {
      "default": 138
    },
    "Omastar": {
      "default": 139
    },
    "Onix": {
      "default": 95
    },
    "Oshawott": {
      "default": 501
    },
    "Pachirisu": {
      "default": 417
    },
    "Palkia": {
      "default": 484
    },
    "Palpitoad": {
      "default": 536
    },
    "Panpour": {
      "default": 515
    },
    "Pansage": {
      "default": 511
    },
    "Pansear": {
      "default": 513
    },
    "Paras": {
      "default": 46
    },
    "Parasect": {
      "default": 47
    },
    "Patrat": {
      "default": 504
    },
    "Pawniard": {
      "default": 624
    },
    "Pelipper": {
      "default": 279
    },
    "Persian": {
      "default": 53
    },
    "Petilil": {
      "default": 548
    },
    "Phanpy": {
      "default": 231
    },
    "Phione": {
      "default": 489
    },
    "Pichu": {
      "default": 172
    },
    "Pidgeot": {
      "default": 18
    },
    "Pidgeotto": {
      "default": 17
    },
    "Pidgey": {
      "default": 16
    },
    "Pidove": {
      "default": 519
    },
    "Pignite": {
      "default": 499
    },
    "Pikachu": {
      "default": 25
    },
    "Piloswine": {
      "default": 221
    },
    "Pineco": {
      "default": 204
    },
    "Pinsir": {
      "default": 127,
      "mega": NON_DEFAULT_FORMES_OFFSET + 120
    },
    "Piplup": {
      "default": 393
    },
    "Plusle": {
      "default": 311
    },
    "Politoed": {
      "default": 186
    },
    "Poliwag": {
      "default": 60
    },
    "Poliwhirl": {
      "default": 61
    },
    "Poliwrath": {
      "default": 62
    },
    "Ponyta": {
      "default": 77
    },
    "Poochyena": {
      "default": 261
    },
    "Porygon": {
      "default": 137
    },
    "Porygon-Z": {
      "default": 474
    },
    "Porygon2": {
      "default": 233
    },
    "Primeape": {
      "default": 57
    },
    "Prinplup": {
      "default": 394
    },
    "Probopass": {
      "default": 476
    },
    "Psyduck": {
      "default": 54
    },
    "Pupitar": {
      "default": 247
    },
    "Purrloin": {
      "default": 509
    },
    "Purugly": {
      "default": 432
    },
    "Quagsire": {
      "default": 195
    },
    "Quilava": {
      "default": 156
    },
    "Qwilfish": {
      "default": 211
    },
    "Raichu": {
      "default": 26
    },
    "Raikou": {
      "default": 243
    },
    "Ralts": {
      "default": 280
    },
    "Rampardos": {
      "default": 409
    },
    "Rapidash": {
      "default": 78
    },
    "Raticate": {
      "default": 20
    },
    "Rattata": {
      "default": 19
    },
    "Rayquaza": {
      "default": 384
    },
    "Regice": {
      "default": 378
    },
    "Regigigas": {
      "default": 486
    },
    "Regirock": {
      "default": 377
    },
    "Registeel": {
      "default": 379
    },
    "Relicanth": {
      "default": 369
    },
    "Remoraid": {
      "default": 223
    },
    "Reshiram": {
      "default": 643
    },
    "Reuniclus": {
      "default": 579
    },
    "Rhydon": {
      "default": 112
    },
    "Rhyhorn": {
      "default": 111
    },
    "Rhyperior": {
      "default": 464
    },
    "Riolu": {
      "default": 447
    },
    "Roggenrola": {
      "default": 524
    },
    "Roselia": {
      "default": 315
    },
    "Roserade": {
      "default": 407
    },
    "Rotom": {
      "default": 479,
      "fan": NON_DEFAULT_FORMES_OFFSET + 68,
      "frost": NON_DEFAULT_FORMES_OFFSET + 69,
      "heat": NON_DEFAULT_FORMES_OFFSET + 70,
      "mow": NON_DEFAULT_FORMES_OFFSET + 71,
      "wash": NON_DEFAULT_FORMES_OFFSET + 72
    },
    "Rufflet": {
      "default": 627
    },
    "Sableye": {
      "default": 302
    },
    "Salamence": {
      "default": 373
    },
    "Samurott": {
      "default": 503
    },
    "Sandile": {
      "default": 551
    },
    "Sandshrew": {
      "default": 27
    },
    "Sandslash": {
      "default": 28
    },
    "Sawk": {
      "default": 539
    },
    "Sawsbuck": {
      "default": 586
    },
    "Sceptile": {
      "default": 254
    },
    "Scizor": {
      "default": 212,
      "mega": NON_DEFAULT_FORMES_OFFSET + 126
    },
    "Scolipede": {
      "default": 545
    },
    "Scrafty": {
      "default": 560
    },
    "Scraggy": {
      "default": 559
    },
    "Scyther": {
      "default": 123
    },
    "Seadra": {
      "default": 117
    },
    "Seaking": {
      "default": 119
    },
    "Sealeo": {
      "default": 364
    },
    "Seedot": {
      "default": 273
    },
    "Seel": {
      "default": 86
    },
    "Seismitoad": {
      "default": 537
    },
    "Sentret": {
      "default": 161
    },
    "Serperior": {
      "default": 497
    },
    "Servine": {
      "default": 496
    },
    "Seviper": {
      "default": 336
    },
    "Sewaddle": {
      "default": 540
    },
    "Sharpedo": {
      "default": 319
    },
    "Shaymin": {
      "default": 492,
      "sky": NON_DEFAULT_FORMES_OFFSET + 76
    },
    "Shedinja": {
      "default": 292
    },
    "Shelgon": {
      "default": 372
    },
    "Shellder": {
      "default": 90
    },
    "Shellos": {
      "default": 422
    },
    "Shelmet": {
      "default": 616
    },
    "Shieldon": {
      "default": 410
    },
    "Shiftry": {
      "default": 275
    },
    "Shinx": {
      "default": 403
    },
    "Shroomish": {
      "default": 285
    },
    "Shuckle": {
      "default": 213
    },
    "Shuppet": {
      "default": 353
    },
    "Sigilyph": {
      "default": 561
    },
    "Silcoon": {
      "default": 266
    },
    "Simipour": {
      "default": 516
    },
    "Simisage": {
      "default": 512
    },
    "Simisear": {
      "default": 514
    },
    "Skarmory": {
      "default": 227
    },
    "Skiploom": {
      "default": 188
    },
    "Skitty": {
      "default": 300
    },
    "Skorupi": {
      "default": 451
    },
    "Skuntank": {
      "default": 435
    },
    "Slaking": {
      "default": 289
    },
    "Slakoth": {
      "default": 287
    },
    "Slowbro": {
      "default": 80
    },
    "Slowking": {
      "default": 199
    },
    "Slowpoke": {
      "default": 79
    },
    "Slugma": {
      "default": 218
    },
    "Smeargle": {
      "default": 235
    },
    "Smoochum": {
      "default": 238
    },
    "Sneasel": {
      "default": 215
    },
    "Snivy": {
      "default": 495
    },
    "Snorlax": {
      "default": 143
    },
    "Snorunt": {
      "default": 361
    },
    "Snover": {
      "default": 459
    },
    "Snubbull": {
      "default": 209
    },
    "Solosis": {
      "default": 577
    },
    "Solrock": {
      "default": 338
    },
    "Spearow": {
      "default": 21
    },
    "Spheal": {
      "default": 363
    },
    "Spinarak": {
      "default": 167
    },
    "Spinda": {
      "default": 327
    },
    "Spiritomb": {
      "default": 442
    },
    "Spoink": {
      "default": 325
    },
    "Squirtle": {
      "default": 7
    },
    "Stantler": {
      "default": 234
    },
    "Staraptor": {
      "default": 398
    },
    "Staravia": {
      "default": 397
    },
    "Starly": {
      "default": 396
    },
    "Starmie": {
      "default": 121
    },
    "Staryu": {
      "default": 120
    },
    "Steelix": {
      "default": 208
    },
    "Stoutland": {
      "default": 508
    },
    "Stunfisk": {
      "default": 618
    },
    "Stunky": {
      "default": 434
    },
    "Sudowoodo": {
      "default": 185
    },
    "Suicune": {
      "default": 245
    },
    "Sunflora": {
      "default": 192
    },
    "Sunkern": {
      "default": 191
    },
    "Surskit": {
      "default": 283
    },
    "Swablu": {
      "default": 333
    },
    "Swadloon": {
      "default": 541
    },
    "Swalot": {
      "default": 317
    },
    "Swampert": {
      "default": 260
    },
    "Swanna": {
      "default": 581
    },
    "Swellow": {
      "default": 277
    },
    "Swinub": {
      "default": 220
    },
    "Swoobat": {
      "default": 528
    },
    "Taillow": {
      "default": 276
    },
    "Tangela": {
      "default": 114
    },
    "Tangrowth": {
      "default": 465
    },
    "Tauros": {
      "default": 128
    },
    "Teddiursa": {
      "default": 216
    },
    "Tentacool": {
      "default": 72
    },
    "Tentacruel": {
      "default": 73
    },
    "Tepig": {
      "default": 498
    },
    "Terrakion": {
      "default": 639
    },
    "Throh": {
      "default": 538
    },
    "Thundurus": {
      "default": 642,
      "therian": NON_DEFAULT_FORMES_OFFSET + 99
    },
    "Timburr": {
      "default": 532
    },
    "Tirtouga": {
      "default": 564
    },
    "Togekiss": {
      "default": 468
    },
    "Togepi": {
      "default": 175
    },
    "Togetic": {
      "default": 176
    },
    "Torchic": {
      "default": 255
    },
    "Torkoal": {
      "default": 324
    },
    "Tornadus": {
      "default": 641,
      "therian": NON_DEFAULT_FORMES_OFFSET + 98
    },
    "Torterra": {
      "default": 389
    },
    "Totodile": {
      "default": 158
    },
    "Toxicroak": {
      "default": 454
    },
    "Tranquill": {
      "default": 520
    },
    "Trapinch": {
      "default": 328
    },
    "Treecko": {
      "default": 252
    },
    "Tropius": {
      "default": 357
    },
    "Trubbish": {
      "default": 568
    },
    "Turtwig": {
      "default": 387
    },
    "Tympole": {
      "default": 535
    },
    "Tynamo": {
      "default": 602
    },
    "Typhlosion": {
      "default": 157
    },
    "Tyranitar": {
      "default": 248,
      "mega": NON_DEFAULT_FORMES_OFFSET + 129
    },
    "Tyrogue": {
      "default": 236
    },
    "Umbreon": {
      "default": 197
    },
    "Unfezant": {
      "default": 521
    },
    "Unown": {
      "default": 201
    },
    "Ursaring": {
      "default": 217
    },
    "Uxie": {
      "default": 480
    },
    "Vanillish": {
      "default": 583
    },
    "Vanillite": {
      "default": 582
    },
    "Vanilluxe": {
      "default": 584
    },
    "Vaporeon": {
      "default": 134
    },
    "Venipede": {
      "default": 543
    },
    "Venomoth": {
      "default": 49
    },
    "Venonat": {
      "default": 48
    },
    "Venusaur": {
      "default": 3,
      "mega": NON_DEFAULT_FORMES_OFFSET + 113
    },
    "Vespiquen": {
      "default": 416
    },
    "Vibrava": {
      "default": 329
    },
    "Victini": {
      "default": 494
    },
    "Victreebel": {
      "default": 71
    },
    "Vigoroth": {
      "default": 288
    },
    "Vileplume": {
      "default": 45
    },
    "Virizion": {
      "default": 640
    },
    "Volbeat": {
      "default": 313
    },
    "Volcarona": {
      "default": 637
    },
    "Voltorb": {
      "default": 100
    },
    "Vullaby": {
      "default": 629
    },
    "Vulpix": {
      "default": 37
    },
    "Wailmer": {
      "default": 320
    },
    "Wailord": {
      "default": 321
    },
    "Walrein": {
      "default": 365
    },
    "Wartortle": {
      "default": 8
    },
    "Watchog": {
      "default": 505
    },
    "Weavile": {
      "default": 461
    },
    "Weedle": {
      "default": 13
    },
    "Weepinbell": {
      "default": 70
    },
    "Weezing": {
      "default": 110
    },
    "Whimsicott": {
      "default": 547
    },
    "Whirlipede": {
      "default": 544
    },
    "Whiscash": {
      "default": 340
    },
    "Whismur": {
      "default": 293
    },
    "Wigglytuff": {
      "default": 40
    },
    "Wingull": {
      "default": 278
    },
    "Wobbuffet": {
      "default": 202
    },
    "Woobat": {
      "default": 527
    },
    "Wooper": {
      "default": 194
    },
    "Wormadam": {
      "default": 413,
      "sandy": NON_DEFAULT_FORMES_OFFSET + 60,
      "trash": NON_DEFAULT_FORMES_OFFSET + 61
    },
    "Wurmple": {
      "default": 265
    },
    "Wynaut": {
      "default": 360
    },
    "Xatu": {
      "default": 178
    },
    "Yamask": {
      "default": 562
    },
    "Yanma": {
      "default": 193
    },
    "Yanmega": {
      "default": 469
    },
    "Zangoose": {
      "default": 335
    },
    "Zapdos": {
      "default": 145
    },
    "Zebstrika": {
      "default": 523
    },
    "Zekrom": {
      "default": 644
    },
    "Zigzagoon": {
      "default": 263
    },
    "Zoroark": {
      "default": 571
    },
    "Zorua": {
      "default": 570
    },
    "Zubat": {
      "default": 41
    },
    "Zweilous": {
      "default": 634
    },
    "Aegislash": {
      "default": 681,
      "blade": NON_DEFAULT_FORMES_OFFSET + 106
    },
    "Amaura": {
      "default": 698
    },
    "Aromatisse": {
      "default": 683
    },
    "Aurorus": {
      "default": 699
    },
    "Avalugg": {
      "default": 713
    },
    "Barbaracle": {
      "default": 689
    },
    "Bergmite": {
      "default": 712
    },
    "Binacle": {
      "default": 688
    },
    "Braixen": {
      "default": 654
    },
    "Bunnelby": {
      "default": 659
    },
    "Carbink": {
      "default": 703
    },
    "Chesnaught": {
      "default": 652
    },
    "Chespin": {
      "default": 650
    },
    "Clawitzer": {
      "default": 693
    },
    "Clauncher": {
      "default": 692
    },
    "Dedenne": {
      "default": 702
    },
    "Delphox": {
      "default": 655
    },
    "Diancie": {
      "default": 719
    },
    "Diggersby": {
      "default": 660
    },
    "Doublade": {
      "default": 680
    },
    "Dragalge": {
      "default": 691
    },
    "Espurr": {
      "default": 677
    },
    "Fennekin": {
      "default": 653
    },
    "Flabébé": {
      "default": 669
    },
    "Fletchinder": {
      "default": 662
    },
    "Fletchling": {
      "default": 661
    },
    "Floette": {
      "default": 670
    },
    "Florges": {
      "default": 671
    },
    "Froakie": {
      "default": 656
    },
    "Frogadier": {
      "default": 657
    },
    "Furfrou": {
      "default": 676
    },
    "Gogoat": {
      "default": 673
    },
    "Goodra": {
      "default": 706
    },
    "Goomy": {
      "default": 704
    },
    "Gourgeist": {
      "default": 711
    },
    "Greninja": {
      "default": 658
    },
    "Hawlucha": {
      "default": 701
    },
    "Heliolisk": {
      "default": 695
    },
    "Helioptile": {
      "default": 694
    },
    "Honedge": {
      "default": 679
    },
    "Hoopa": {
      "default": 720
    },
    "Inkay": {
      "default": 686
    },
    "Klefki": {
      "default": 707
    },
    "Litleo": {
      "default": 667
    },
    "Malamar": {
      "default": 687
    },
    "Meowstic": {
      "default": 678,
      "female": NON_DEFAULT_FORMES_OFFSET + 105
    },
    "Noibat": {
      "default": 714
    },
    "Noivern": {
      "default": 715
    },
    "Pancham": {
      "default": 674
    },
    "Pangoro": {
      "default": 675
    },
    "Phantump": {
      "default": 708
    },
    "Pumpkaboo": {
      "default": 710
    },
    "Pyroar": {
      "default": 668
    },
    "Quilladin": {
      "default": 651
    },
    "Scatterbug": {
      "default": 664
    },
    "Skiddo": {
      "default": 672
    },
    "Skrelp": {
      "default": 690
    },
    "Sliggoo": {
      "default": 705
    },
    "Slurpuff": {
      "default": 685
    },
    "Spewpa": {
      "default": 665
    },
    "Spritzee": {
      "default": 682
    },
    "Swirlix": {
      "default": 684
    },
    "Sylveon": {
      "default": 700
    },
    "Talonflame": {
      "default": 663
    },
    "Trevenant": {
      "default": 709
    },
    "Tyrantrum": {
      "default": 697
    },
    "Tyrunt": {
      "default": 696
    },
    "Vivillon": {
      "default": 666
    },
    "Volcanion": {
      "default": 721
    },
    "Xerneas": {
      "default": 716
    },
    "Yveltal": {
      "default": 717
    },
    "Zygarde": {
      "default": 718
    }
  };

}).call(this);

(function() {
  PokeBattle.modal = function(modalPath, domId, options, initialize) {
    var $modal, id, _ref, _ref1;
    if (!_.isString(domId)) {
      _ref = [null, domId, options], domId = _ref[0], options = _ref[1], initialize = _ref[2];
    }
    if (_.isFunction(options)) {
      _ref1 = [{}, options], options = _ref1[0], initialize = _ref1[1];
    }
    $modal = $(JST[modalPath](options));
    id = '#' + (domId || $modal.prop('id'));
    if ($(id).length === 0) {
      $modal.appendTo($('body'));
      if (typeof initialize === "function") {
        initialize($modal);
      }
    } else {
      $modal = $(id).last();
    }
    $modal.modal('show');
    return $modal;
  };

}).call(this);

(function() {
  var Aliases, HiddenPower, convertNameToSpeciesAndForme, reverseStatsHash, statsHash;

  HiddenPower = (typeof module !== "undefined" && module !== null ? require('../../../../shared/hidden_power') : window.HiddenPower != null ? window.HiddenPower : window.HiddenPower = {});

  if (this.PokeBattle == null) {
    this.PokeBattle = {};
  }

  this.PokeBattle.parseTeam = function(teamString) {
    var all, ev, evs, gender, hiddenPowerType, item, iv, ivs, line, moveName, newability, newitem, newmove, numberString, oldability, olditem, oldmove, pokemon, pokemonLine, pokemonRegex, rawStat, team, text, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
    text = teamString.split('\n');
    team = [];
    pokemonRegex = /^(.*?)\s*(\(M\)|\(F\)|)?(?:\s*@\s*(.*))?$/;
    pokemon = null;
    for (_i = 0, _len = text.length; _i < _len; _i++) {
      line = text[_i];
      line = line.trim();
      if (line.length === 0) {
        pokemon = null;
      } else if (!pokemon) {
        _ref = line.match(pokemonRegex), all = _ref[0], pokemonLine = _ref[1], gender = _ref[2], item = _ref[3];
        pokemon = {};
        team.push(pokemon);
        if (pokemonLine.match(/(.*?)\s*\((.*)\)/)) {
          pokemon.name = RegExp.$1;
          pokemonLine = RegExp.$2;
        }
        convertNameToSpeciesAndForme(pokemon, pokemonLine.trim());
        if (gender) {
          pokemon.gender = gender[1];
        }
        if (item) {
          pokemon.item = item;
        }
        _ref1 = Aliases.items;
        for (olditem in _ref1) {
          newitem = _ref1[olditem];
          if (olditem === pokemon.item) {
            pokemon.item = newitem;
          }
        }
      } else if (line.match(/^(?:Trait|Ability):\s+(.*)$/i)) {
        pokemon.ability = RegExp.$1;
        _ref2 = Aliases.abilities;
        for (oldability in _ref2) {
          newability = _ref2[oldability];
          if (pokemon.ability === oldability) {
            pokemon.ability = newability;
          }
        }
      } else if (line.match(/^Level:\s+(.*)$/i)) {
        pokemon.level = Number(RegExp.$1) || 100;
      } else if (line.match(/^Happiness:\s+(.*)$/i)) {
        pokemon.happiness = Number(RegExp.$1) || 0;
      } else if (line.match(/^Shiny: Yes$/i)) {
        pokemon.shiny = true;
      } else if (line.match(/^EVs: (.*)$/i)) {
        evs = RegExp.$1.split(/\//g);
        pokemon.evs = {};
        for (_j = 0, _len1 = evs.length; _j < _len1; _j++) {
          ev = evs[_j];
          ev = ev.trim();
          _ref3 = ev.split(/\s+/), numberString = _ref3[0], rawStat = _ref3[1];
          pokemon.evs[statsHash[rawStat]] = Number(numberString) || 0;
        }
      } else if (line.match(/^IVs: (.*)$/i)) {
        ivs = RegExp.$1.split(/\//g);
        pokemon.ivs = {};
        for (_k = 0, _len2 = ivs.length; _k < _len2; _k++) {
          iv = ivs[_k];
          iv = iv.trim();
          _ref4 = iv.split(/\s+/), numberString = _ref4[0], rawStat = _ref4[1];
          pokemon.ivs[statsHash[rawStat]] = Number(numberString) || 0;
        }
      } else if (line.match(/^([A-Za-z]+) nature/i)) {
        pokemon.nature = RegExp.$1;
      } else if (line.match(/^[\-\~]\s*(.*)/)) {
        moveName = RegExp.$1;
        _ref5 = Aliases.moves;
        for (oldmove in _ref5) {
          newmove = _ref5[oldmove];
          if (moveName === oldmove) {
            moveName = newmove;
          }
        }
        if (/Hidden Power /.test(moveName)) {
          if (!pokemon.ivs) {
            moveName.match(/Hidden Power (.*)/i);
            hiddenPowerType = RegExp.$1.trim().toLowerCase().replace(/\W+/g, '');
            pokemon.ivs = HiddenPower.BW.ivs[hiddenPowerType] || {};
          }
          moveName = 'Hidden Power';
        }
        if (pokemon.moves == null) {
          pokemon.moves = [];
        }
        pokemon.moves.push(moveName);
      }
    }
    return team;
  };

  this.PokeBattle.exportTeam = function(json) {
    var amount, evArray, ivArray, mainLine, moveName, pokemon, s, species, stat, _i, _j, _len, _len1, _ref;
    s = [];
    for (_i = 0, _len = json.length; _i < _len; _i++) {
      pokemon = json[_i];
      s.push("");
      species = pokemon.species;
      if (pokemon.forme && pokemon.forme !== "default") {
        species += "-" + (pokemon.forme[0].toUpperCase());
      }
      mainLine = [];
      if (pokemon.name) {
        mainLine.push(pokemon.name);
        mainLine.push("(" + species + ")");
      } else {
        mainLine.push(species);
      }
      if (pokemon.gender) {
        mainLine.push("(" + pokemon.gender + ")");
      }
      if (pokemon.item) {
        mainLine.push("@ " + pokemon.item);
      }
      s.push(mainLine.join(' '));
      if (pokemon.ability) {
        s.push("Ability: " + pokemon.ability);
      }
      if (pokemon.evs) {
        evArray = (function() {
          var _ref, _results;
          _ref = pokemon.evs;
          _results = [];
          for (stat in _ref) {
            amount = _ref[stat];
            if (amount > 0) {
              _results.push("" + amount + " " + reverseStatsHash[stat]);
            }
          }
          return _results;
        })();
        if (evArray.length > 0) {
          s.push("EVs: " + (evArray.join(" / ")));
        }
      }
      if (pokemon.ivs) {
        ivArray = (function() {
          var _ref, _results;
          _ref = pokemon.ivs;
          _results = [];
          for (stat in _ref) {
            amount = _ref[stat];
            if (amount < 31) {
              _results.push("" + amount + " " + reverseStatsHash[stat]);
            }
          }
          return _results;
        })();
        if (ivArray.length > 0) {
          s.push("IVs: " + (ivArray.join(" / ")));
        }
      }
      if (pokemon.nature) {
        s.push("" + pokemon.nature + " nature");
      }
      if (pokemon.level && pokemon.level !== 100) {
        s.push("Level: " + pokemon.level);
      }
      if (pokemon.shiny) {
        s.push("Shiny: Yes");
      }
      if (pokemon.happiness && pokemon.happiness !== 100) {
        s.push("Happiness: " + pokemon.happiness);
      }
      if (pokemon.moves) {
        _ref = pokemon.moves;
        for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
          moveName = _ref[_j];
          s.push("- " + moveName);
        }
      }
    }
    s.push("\n");
    return s.join("\n");
  };

  Aliases = {
    moves: {
      "Ancient Power": "AncientPower",
      "Bubble Beam": "BubbleBeam",
      "Double Slap": "DoubleSlap",
      "Dragon Breath": "DragonBreath",
      "Dynamic Punch": "DynamicPunch",
      "Extreme Speed": "ExtremeSpeed",
      "Feint Attack": "Faint Attack",
      "Feather Dance": "FeatherDance",
      "Grass Whistle": "GrassWhistle",
      "High Jump Kick": "Hi Jump Kick",
      "Poison Powder": "PoisonPowder",
      "Sand Attack": "Sand-Attack",
      "Self-Destruct": "Selfdestruct",
      "Smelling Salts": "SmellingSalt",
      "Smokescreen": "SmokeScreen",
      "Soft-Boiled": "Softboiled",
      "Solar Beam": "SolarBeam",
      "Sonic Boom": "SonicBoom",
      "Thunder Punch": "ThunderPunch",
      "Thunder Shock": "ThunderShock",
      "Vice Grip": "ViceGrip"
    },
    abilities: {
      "Compound Eyes": "Compoundeyes",
      "Lightning Rod": "Lightningrod"
    },
    items: {
      "Balm Mushroom": "BalmMushroom",
      "Black Glasses": "BlackGlasses",
      "Bright Powder": "BrightPowder",
      "Deep Sea Scale": "DeepSeaScale",
      "Deep Sea Tooth": "DeepSeaTooth",
      "Energy Powder": "EnergyPowder",
      "Never-Melt Ice": "NeverMeltIce",
      "Paralyze Heal": "Parlyz Heal",
      "Rage Candy Bar": "RageCandyBar",
      "Silver Powder": "SilverPowder",
      "Thunder Stone": "Thunderstone",
      "Tiny Mushroom": "TinyMushroom",
      "Twisted Spoon": "TwistedSpoon",
      "X Defense": "X Defend",
      "X Sp. Atk": "X Special"
    }
  };

  statsHash = {
    'hp': 'hp',
    'Hp': 'hp',
    'HP': 'hp',
    'Atk': 'attack',
    'Def': 'defense',
    'SAtk': 'specialAttack',
    'SpA': 'specialAttack',
    'SDef': 'specialDefense',
    'SpD': 'specialDefense',
    'Spe': 'speed',
    'Spd': 'speed'
  };

  reverseStatsHash = {
    'hp': 'HP',
    'attack': 'Atk',
    'defense': 'Def',
    'specialAttack': 'SAtk',
    'specialDefense': 'SDef',
    'speed': 'Spe'
  };

  convertNameToSpeciesAndForme = function(pokemon, species) {
    if (species.match(/(Thundurus|Landorus|Tornadus)\-T(herian)?/i)) {
      pokemon.species = RegExp.$1;
      return pokemon.forme = 'therian';
    } else if (species.match(/Shaymin-S(ky)?/i)) {
      pokemon.species = "Shaymin";
      return pokemon.forme = 'sky';
    } else if (species.match(/Giratina-O(rigin)?/i)) {
      pokemon.species = "Giratina";
      return pokemon.forme = 'origin';
    } else if (species.match(/Arceus(\-.*)?/)) {
      return pokemon.species = "Arceus";
    } else if (species.match(/Kyurem-B(lack)?/)) {
      pokemon.species = "Kyurem";
      return pokemon.forme = "black";
    } else if (species.match(/Kyurem-W(hite)?/)) {
      pokemon.species = "Kyurem";
      return pokemon.forme = "white";
    } else if (species.match(/Rotom-W|Rotom-Wash/)) {
      pokemon.species = "Rotom";
      return pokemon.forme = "wash";
    } else if (species.match(/Rotom-S|Rotom-Fan/)) {
      pokemon.species = "Rotom";
      return pokemon.forme = "fan";
    } else if (species.match(/Rotom-H|Rotom-Heat/)) {
      pokemon.species = "Rotom";
      return pokemon.forme = "heat";
    } else if (species.match(/Rotom-F|Rotom-Frost/)) {
      pokemon.species = "Rotom";
      return pokemon.forme = "frost";
    } else if (species.match(/Rotom-C|Rotom-Mow/)) {
      pokemon.species = "Rotom";
      return pokemon.forme = "mow";
    } else if (species.match(/Deoxys-A|Deoxys-Attack/)) {
      pokemon.species = "Deoxys";
      return pokemon.forme = "attack";
    } else if (species.match(/Deoxys-D|Deoxys-Defense/)) {
      pokemon.species = "Deoxys";
      return pokemon.forme = "defense";
    } else if (species.match(/Deoxys-S|Deoxys-Speed/)) {
      pokemon.species = "Deoxys";
      return pokemon.forme = "speed";
    } else if (species.match(/Basculin-Blue-Striped|Basculin-A/)) {
      pokemon.species = "Basculin";
      return pokemon.forme = "blue-striped";
    } else if (species.match(/Keldeo-Resolute|Keldeo-R/)) {
      pokemon.species = "Keldeo";
      return pokemon.forme = "resolute";
    } else if (species.match(/Shellos-East/)) {
      pokemon.species = "Shellos";
      return pokemon.forme = "default";
    } else if (species.match(/Gastrodon-East/)) {
      pokemon.species = "Gastrodon";
      return pokemon.forme = "default";
    } else if (species.match(/Wormadam-Sandy|Wormadam-G/)) {
      pokemon.species = "Wormadam";
      return pokemon.forme = "sandy";
    } else if (species.match(/Wormadam-Trash|Wormadam-S/)) {
      pokemon.species = "Wormadam";
      return pokemon.forme = "trash";
    } else if (species.match(/Deerling-.*/)) {
      pokemon.species = "Deerling";
      return pokemon.forme = null;
    } else if (species.match(/Sawsbuck-.*/)) {
      pokemon.species = "Sawsbuck";
      return pokemon.forme = null;
    } else if (species.match(/Unown-.*/)) {
      pokemon.species = "Unown";
      return pokemon.forme = null;
    } else {
      return pokemon.species = species;
    }
  };

}).call(this);

(function() {
  PokeBattle.humanizeTime = (function(_this) {
    return function(unixTime) {
      var minutes, seconds;
      if ((unixTime == null) || unixTime < 0) {
        unixTime = 0;
      }
      seconds = Math.floor(unixTime / 1000) % 60;
      minutes = Math.floor(unixTime / 1000 / 60);
      seconds = String(seconds);
      return minutes + ":" + "00".substr(seconds.length) + seconds;
    };
  })(this);

  $(function() {
    return window.setInterval(function() {
      return $(".elapsed-time").each(function() {
        var $el, elapsedTime;
        $el = $(this);
        elapsedTime = Date.now() - $el.data("time-start");
        return $el.text(PokeBattle.humanizeTime(elapsedTime));
      });
    }, 500);
  });

}).call(this);

(function() {
  var $currentModal;

  $currentModal = null;

  PokeBattle.primus.on('achievementsEarned', function(achievements) {
    return $currentModal = PokeBattle.modal('modals/achievements', {
      window: window,
      achievements: achievements
    });
  });

}).call(this);

(function() {
  PokeBattle.primus.on('altList', function(list) {
    return PokeBattle.alts.list = list;
  });

  PokeBattle.primus.on('altCreated', function(altName) {
    return PokeBattle.alts.list.push(altName);
  });

  PokeBattle.alts = {
    list: [],
    createAlt: function(altName) {
      return PokeBattle.primus.send('createAlt', altName);
    }
  };

}).call(this);

(function() {
  PokeBattle.battles.on('remove', function(battle) {
    return PokeBattle.primus.send('leaveChatroom', battle.id);
  });

  PokeBattle.primus.on('updateBattle', function(id, queue) {
    var battle;
    battle = PokeBattle.battles.get(id);
    if (!battle) {
      console.log("Received events for " + id + ", but no longer in battle!");
      return;
    }
    return battle.update(queue);
  });

  PokeBattle.primus.on('spectateBattle', function(id, format, numActive, index, playerIds, log) {
    var $battle, battle;
    if (PokeBattle.battles.get(id)) {
      console.log("Already spectating battle " + id + "!");
      return;
    }
    battle = new Battle({
      id: id,
      format: format,
      numActive: numActive,
      index: index,
      playerIds: playerIds
    });
    $battle = $(JST['battle_window']({
      battle: battle,
      window: window
    }));
    $('#main-section').append($battle);
    battle.view = new BattleView({
      el: $battle,
      model: battle
    });
    battle.view.skip = 0;
    battle.view.$('.battle_pane').hide();
    PokeBattle.battles.add(battle);
    return battle.update(log);
  });

  PokeBattle.primus.on('updateTimers', function(id, timers) {
    var battle;
    battle = PokeBattle.battles.get(id);
    if (!battle) {
      console.log("Received events for " + id + ", but no longer in battle!");
      return;
    }
    return battle.view.updateTimers(timers);
  });

  PokeBattle.primus.on('resumeTimer', function(id, player) {
    var battle;
    battle = PokeBattle.battles.get(id);
    if (!battle) {
      console.log("Received events for " + id + ", but no longer in battle!");
      return;
    }
    return battle.view.resumeTimer(player);
  });

  PokeBattle.primus.on('pauseTimer', function(id, player, timeSinceLastAction) {
    var battle;
    battle = PokeBattle.battles.get(id);
    if (!battle) {
      console.log("Received events for " + id + ", but no longer in battle!");
      return;
    }
    return battle.view.pauseTimer(player, timeSinceLastAction);
  });

}).call(this);

(function() {
  PokeBattle.primus.on('battleList', function(battles) {
    return PokeBattle.battleList.refreshListComplete(battles);
  });

}).call(this);

(function() {
  var Commands, dataAbility, dataItem, dataMove, dataPokemon, desc, findAbility, findItem, findMove, findPokemon, findPokemonAtPBV, findTotalPBV, formatName, linkToDex, makeCommand, normalize, parseCommand, pokemonIcon, slugify,
    __slice = [].slice;

  if (PokeBattle.commands == null) {
    PokeBattle.commands = {};
  }

  Commands = {};

  desc = function(description) {
    return desc.lastDescription = description;
  };

  makeCommand = function() {
    var aliases, commandName, commandNames, description, func, _i, _j, _len;
    commandNames = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), func = arguments[_i++];
    for (_j = 0, _len = commandNames.length; _j < _len; _j++) {
      commandName = commandNames[_j];
      Commands[commandName] = func;
    }
    description = "";
    if (commandNames.length > 1) {
      aliases = commandNames.slice(1).map(function(n) {
        return "/" + n;
      }).join(', ');
      description += " <i>Also " + aliases + ". </i>";
    }
    description += desc.lastDescription;
    HelpDescriptions['1'][commandNames[0]] = description;
    return delete desc.lastDescription;
  };

  parseCommand = function(line) {
    var args, commandName, _ref;
    _ref = line.split(/\s+/), commandName = _ref[0], args = 2 <= _ref.length ? __slice.call(_ref, 1) : [];
    if (commandName[0] === '/') {
      commandName = commandName.slice(1);
      args = args.join(' ').split(/,/g);
      return [commandName, args];
    }
    return null;
  };

  PokeBattle.commands.execute = function(room, line) {
    var args, command, commandName, result;
    result = parseCommand(line);
    if (!result) {
      return false;
    }
    commandName = result[0], args = result[1];
    command = Commands[commandName];
    if (!command) {
      return false;
    }
    command.apply(null, [room].concat(__slice.call(args)));
    return true;
  };

  desc('Displays a list of all commands.');

  makeCommand("commands", "help", "h", function(room) {
    var authLevels, description, descriptions, humanLevel, level, message, name, user;
    user = room.get('users').get(PokeBattle.username);
    for (level in HelpDescriptions) {
      descriptions = HelpDescriptions[level];
      level = Number(level);
      if (user.get('authority') < level) {
        continue;
      }
      message = [];
      authLevels = {
        1: "USER",
        2: "DRIVER",
        3: "MOD",
        4: "ADMIN",
        5: "OWNER"
      };
      humanLevel = authLevels[level];
      message.push("<b>" + humanLevel + " COMMANDS:</b>");
      for (name in descriptions) {
        description = descriptions[name];
        message.push("<b>/" + name + ":</b> " + description);
      }
      message = message.join("<br>");
      room.announce('success', message);
    }
    return true;
  });

  desc('Opens the challenge for a specific user. Usage: /challenge username');

  makeCommand("challenge", "chall", "c", function(room, username) {
    var message;
    if (!username) {
      PokeBattle.events.trigger("errorMessage", "Usage: /challenge username");
      return;
    }
    message = PokeBattle.messages.add({
      id: username
    });
    return message.openChallenge(username);
  });

  desc('Private messages a certain user. Usage: /message username, message');

  makeCommand("message", "msg", "pm", "whisper", "w", function() {
    var message, messages, room, text, username;
    room = arguments[0], username = arguments[1], messages = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
    username = username != null ? username.trim() : void 0;
    if (!username) {
      PokeBattle.events.trigger("errorMessage", "Usage: /message username, msg");
      return;
    }
    message = PokeBattle.messages.add({
      id: username
    });
    if (messages.length > 0) {
      text = messages.join(',');
      return PokeBattle.primus.send('privateMessage', message.id, text);
    } else {
      return message.trigger('open', message);
    }
  });

  desc('Clears the chat.');

  makeCommand("clear", function(room) {
    return room.clear();
  });

  desc('Displays a Pokemon\'s PokeBattle value, or displays all Pokemon at or under a particular PBV. Usage: /pbv pkmn1, pkmn2, OR /pbv number');

  makeCommand("pbv", function() {
    var messages, pbv, pokemon, room;
    room = arguments[0], pokemon = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
    pbv = Number(pokemon[0]);
    if (!isNaN(pbv)) {
      messages = findPokemonAtPBV(pbv);
    } else {
      messages = findTotalPBV(pokemon);
    }
    if (messages.length === 0) {
      return room.announce('error', "<b>PBV error:</b> Enter valid Pokemon or PBV.");
    } else {
      return room.announce('success', "<b>PBV:</b> " + (messages.join('; ')));
    }
  });

  findPokemonAtPBV = function(pbv) {
    var counter, dexEntry, formattedName, formeData, formeName, formes, icon, messages, plural, speciesName, _ref;
    messages = [];
    counter = 0;
    _ref = window.Generations.XY.FormeData;
    for (speciesName in _ref) {
      formes = _ref[speciesName];
      for (formeName in formes) {
        formeData = formes[formeName];
        if (formeData.pokeBattleValue <= pbv) {
          counter += 1;
          dexEntry = "pokemon/" + (slugify(speciesName)) + "/" + (slugify(formeName));
          icon = pokemonIcon(speciesName, formeName);
          formattedName = formatName(speciesName, formeName);
          messages.push("" + (linkToDex(dexEntry, icon + formattedName)) + ": " + formeData.pokeBattleValue);
        }
      }
    }
    if (messages.length > 10) {
      messages = _.sample(messages, 10);
      messages.push(linkToDex("pokemon/?pbv=<" + (pbv + 1), "See more Pokemon &raquo;"));
    }
    if (messages.length > 0) {
      plural = messages.length === 1 ? "is" : "are";
      messages.unshift("There " + plural + " " + counter + " Pokemon with a PBV of " + pbv + " or less");
    }
    return messages;
  };

  findTotalPBV = function(pokemon) {
    var array, dexEntry, formattedName, formeName, icon, messages, pbv, speciesName, total, _i, _len;
    pokemon = _(pokemon).map(findPokemon);
    messages = [];
    total = 0;
    for (_i = 0, _len = pokemon.length; _i < _len; _i++) {
      array = pokemon[_i];
      if (!array) {
        continue;
      }
      speciesName = array[0], formeName = array[1];
      pbv = PokeBattle.PBV.determinePBV(window.Generations.XY, {
        species: speciesName,
        forme: formeName
      });
      total += pbv;
      dexEntry = "pokemon/" + (slugify(speciesName)) + "/" + (slugify(formeName));
      icon = pokemonIcon(speciesName, formeName);
      formattedName = formatName(speciesName, formeName);
      messages.push("" + (linkToDex(dexEntry, icon + formattedName)) + ": " + pbv);
    }
    if (messages.length > 1) {
      messages.push("Total: " + total);
    }
    return messages;
  };

  desc('Looks up information about a Pokemon, move, item, or ability.');

  makeCommand("data", "dex", function(room, query) {
    var ability, item, message, move, pokemon;
    if ((pokemon = findPokemon(query))) {
      message = dataPokemon(pokemon);
    } else if ((item = findItem(query))) {
      message = dataItem(item);
    } else if ((move = findMove(query))) {
      message = dataMove(move);
    } else if ((ability = findAbility(query))) {
      message = dataAbility(ability);
    } else {
      room.announce("error", "<b>Data error:</b> Enter a valid Pokemon, item, move, or ability.</div>");
      return;
    }
    return room.announce('success', message);
  });

  dataPokemon = function(pokemon) {
    var abilities, forme, formeName, formeSlug, hiddenAbility, message, pokeBattleValue, speciesName, speciesSlug, statNames, stats, statsText, types, _ref;
    speciesName = pokemon[0], formeName = pokemon[1];
    _ref = [slugify(speciesName), slugify(formeName)], speciesSlug = _ref[0], formeSlug = _ref[1];
    forme = window.Generations.XY.FormeData[speciesName][formeName];
    types = forme.types, abilities = forme.abilities, hiddenAbility = forme.hiddenAbility, stats = forme.stats, pokeBattleValue = forme.pokeBattleValue;
    abilities = _.clone(abilities);
    if (hiddenAbility != null) {
      abilities.push(hiddenAbility);
    }
    abilities = _(abilities).map(function(a) {
      return linkToDex("abilities/" + (slugify(a)), a);
    });
    abilities = abilities.join('/');
    if (hiddenAbility != null) {
      abilities += " (H)";
    }
    types = _(types).map(function(t) {
      return linkToDex("types/" + (slugify(t)), "<img src='" + (window.TypeSprite(t)) + "' alt='" + t + "'/>");
    });
    statNames = ['HP', 'Attack', 'Defense', 'Sp.Attack', 'Sp.Defense', 'Speed'];
    stats = [stats.hp, stats.attack, stats.defense, stats.specialAttack, stats.specialDefense, stats.speed];
    statsText = _.map(_.zip(statNames, stats), function(a) {
      return a.join(': ');
    }).join(' / ');
    message = "" + (pokemonIcon(speciesName, formeName, "left")) + "\n<p class=\"ml3\">\n<b>" + (formatName(speciesName, formeName)) + ":</b> " + (types.join('')) + " |\n" + abilities + "<br />" + statsText + " |\n" + (_(stats).reduce(function(a, b) {
      return a + b;
    })) + " <abbr title=\"Base Stat Total\">BST</abbr>\n| <abbr title=\"PokeBattle Value\">PBV</abbr>: " + pokeBattleValue + "\n" + (linkToDex("pokemon/" + speciesSlug + "/" + formeSlug, "See dex entry &raquo;")) + "\n</p>";
    return message;
  };

  dataItem = function(itemName) {
    var item, message;
    item = window.Generations.XY.ItemData[itemName];
    message = "<b>" + itemName + ":</b> " + item.description;
    if (item.naturalGift) {
      message += " Natural Gift is " + item.naturalGift.type + " type and has " + item.naturalGift.power + " base power.";
    }
    if (item.flingPower) {
      message += " Fling has " + item.flingPower + " base power.";
    }
    if (item.unreleased) {
      message += " Currently unreleased in Gen 6.";
    }
    return message;
  };

  dataMove = function(moveName) {
    var acc, category, maxpp, message, move, power, priority, target, type;
    move = window.Generations.XY.MoveData[moveName];
    type = linkToDex("types/" + (slugify(move.type)), "<img src='" + (window.TypeSprite(move.type)) + "' alt='" + move.type + "'/>");
    category = "<img src=\"" + (CategorySprite(move.damage)) + "\"\nalt=\"" + move.damage + "\"/>";
    target = "<img src=\"" + (TargetSprite(move)) + "\"\nalt=\"" + move.target + "\"/>";
    power = move.power || "&mdash;";
    acc = move.accuracy || "&mdash;";
    maxpp = Math.floor(move.pp * 8 / 5);
    if (move.priority > 0) {
      priority = "+" + move.priority;
    } else if (move.priority < 0) {
      priority = move.priority;
    }
    message = "<b>" + moveName + ":</b> " + type + " " + category + " " + target + " ";
    message += "<b>Power:</b> " + power + " <b>Acc:</b> " + acc + " <b>PP:</b> " + move.pp + " (max " + maxpp + ")";
    message += "<br />";
    if (priority) {
      message += "Priority " + priority + ". ";
    }
    message += move.description;
    message += " ";
    message += linkToDex("moves/" + (slugify(moveName)), "See who learns this move &raquo;");
    return message;
  };

  dataAbility = function(abilityName) {
    var ability, message;
    ability = window.Generations.XY.AbilityData[abilityName];
    message = "<b>" + abilityName + ":</b> " + ability.description + "\n" + (linkToDex("abilities/" + (slugify(abilityName)), "See who obtains this ability &raquo;"));
    return message;
  };

  findPokemon = function(pokemonName) {
    var formeName, name, speciesData, speciesName, _ref;
    pokemonName = normalize(pokemonName);
    _ref = window.Generations.XY.FormeData;
    for (speciesName in _ref) {
      speciesData = _ref[speciesName];
      for (formeName in speciesData) {
        name = speciesName;
        if (formeName !== 'default') {
          name += formeName;
        }
        name = normalize(name);
        name += name;
        if (name.indexOf(pokemonName) !== -1) {
          return [speciesName, formeName];
        }
      }
    }
    return null;
  };

  findItem = function(itemName) {
    var name, normalized;
    normalized = normalize(itemName);
    for (name in window.Generations.XY.ItemData) {
      if (normalized === normalize(name)) {
        return name;
      }
    }
    return null;
  };

  findMove = function(moveName) {
    var name, normalized;
    normalized = normalize(moveName);
    for (name in window.Generations.XY.MoveData) {
      if (normalized === normalize(name)) {
        return name;
      }
    }
    return null;
  };

  findAbility = function(abilityName) {
    var name, normalized;
    normalized = normalize(abilityName);
    for (name in window.Generations.XY.AbilityData) {
      if (normalized === normalize(name)) {
        return name;
      }
    }
    return null;
  };

  slugify = function(str) {
    return str.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/\-{2,}/g, '-');
  };

  normalize = function(str) {
    return str.trim().toLowerCase().replace(/[^a-zA-Z0-9]+/g, '');
  };

  formatName = function(speciesName, formeName) {
    var pokemonName;
    if (formeName === 'default') {
      pokemonName = speciesName;
    } else {
      pokemonName = speciesName;
      pokemonName += ' ';
      pokemonName += formeName.split('-').map(function(n) {
        return n[0].toUpperCase() + n.slice(1);
      }).join('-');
    }
    return pokemonName;
  };

  linkToDex = function(slug, text) {
    return "<a href='//pokebattle.com/dex/" + slug + "' target='_blank'>" + text + "</a>";
  };

  pokemonIcon = function(speciesName, formeName, classes) {
    var style;
    if (classes == null) {
      classes = "";
    }
    style = window.PokemonIconBackground(speciesName, formeName);
    return "<span class=\"pokemon_icon " + classes + "\" style=\"" + style + "\"></span>";
  };

}).call(this);

(function() {
  var $body, $popup, reconnectTimer;

  $body = $("body");

  $popup = $('#popup');

  PokeBattle.primus.on('open', function() {
    $popup.hide();
    return PokeBattle.rooms.rawMessage("Connected to the server!", {
      "class": "yellow italic"
    });
  });

  PokeBattle.primus.on('reconnecting', function() {
    return PokeBattle.rooms.rawMessage("Lost connection to the server...", {
      "class": "red italic"
    });
  });

  PokeBattle.primus.on('end', function() {
    return PokeBattle.rooms.rawMessage("Connection terminated!", {
      "class": "red italic"
    });
  });

  PokeBattle.primus.on('reconnecting', function(opts) {
    var $div, seconds;
    seconds = Math.floor(opts.timeout / 1000);
    if ($popup.length === 0) {
      $popup = $('<div id="popup" class="reconnect popup-absolute"/>').hide();
      $div = $('<span/>').addClass('alert').html("<strong>You lost your connection to PokeBattle!</strong> <span class='reconnect-text'></span>").appendTo($popup);
      $popup.appendTo($body);
    }
    $popup.find('.reconnect-text').html("Reconnecting in\n<span class='reconnect-timer'>" + seconds + "</span> seconds...");
    $popup.fadeIn(250);
    $body.data('seconds', seconds);
    return reconnectTimer($popup);
  });

  reconnectTimer = function($popup) {
    var seconds, time, _ref;
    seconds = (_ref = $body.data('seconds')) != null ? _ref : 1;
    if (seconds === 0) {
      return $popup.find('.reconnect-text').text("Reconnecting...");
    } else {
      time = "" + (Math.floor(seconds / 60)) + ":";
      time += ("00" + (seconds % 60)).substr(-2);
      $popup.find('.reconnect-timer').text(time);
      $body.data('seconds', seconds - 1);
      return setTimeout(reconnectTimer.bind(this, $popup), 1000);
    }
  };

}).call(this);

(function() {
  var __slice = [].slice;

  PokeBattle.primus.on('errorMessage', function() {
    var args, _ref;
    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
    return (_ref = PokeBattle.events).trigger.apply(_ref, ['errorMessage'].concat(__slice.call(args)));
  });

  PokeBattle.events.on("errorMessage", function() {
    var $modal, args, battleId, body, e, errors, length, message, messageText, options, reason, roomId, toUser, type, _ref;
    type = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
    e = PokeBattle.errors;
    switch (type) {
      case e.INVALID_SESSION:
        if ($('#errors-modal').length > 0) {
          $('#errors-modal').remove();
        }
        options = {
          title: "Your login timed out!",
          body: "To access the simulator, you need to\n<a href=\"http://91.121.152.74/\">login again</a>."
        };
        $modal = PokeBattle.modal('modals/errors', options);
        $modal.find('.modal-footer button').first().focus();
        return PokeBattle.primus.end();
      case e.BANNED:
        if ($('#errors-modal').length > 0) {
          $('#errors-modal').remove();
        }
        reason = args[0], length = args[1];
        if (length < 0) {
          length = "is permanent";
        } else {
          length = "lasts for " + (Math.round(length / 60)) + " minute(s)";
        }
        body = "This ban " + length + ".";
        if (reason) {
          body += "You were banned for the following reason: " + reason;
        }
        options = {
          title: "You have been banned!",
          body: body
        };
        $modal = PokeBattle.modal('modals/errors', options);
        $modal.find('.modal-footer button').first().focus();
        return PokeBattle.primus.end();
      case e.FIND_BATTLE:
        PokeBattle.events.trigger("findBattleCanceled");
        errors = args[0];
        return alert(errors);
      case e.BATTLE_DNE:
        battleId = args[0];
        message = 'This battle no longer exists.';
        return (_ref = PokeBattle.rooms.get(battleId)) != null ? _ref.announce('error', message) : void 0;
      case e.COMMAND_ERROR:
        roomId = args[0], message = args[1];
        return PokeBattle.rooms.get(roomId).announce('error', message);
      case e.PRIVATE_MESSAGE:
        toUser = args[0], messageText = args[1];
        message = PokeBattle.messages.get(toUser);
        return message.add(toUser, messageText, {
          type: "error"
        });
      case e.INVALID_ALT_NAME:
        messageText = args[0];
        alert(messageText);
        return PokeBattle.events.trigger("invalidAltName");
      default:
        console.log("Received error: " + type);
        return console.log("  with content: " + args);
    }
  });

}).call(this);

(function() {
  $(window).on('beforeunload', function() {
    if (PokeBattle.battles.isPlaying()) {
      return "You are currently in a battle.";
    } else {

    }
  });

}).call(this);

(function() {
  var __slice = [].slice;

  PokeBattle.primus.on('data', function() {
    var args;
    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
    try {
      if (window.localStorage.debug === 'true') {
        return console.log.apply(console, args);
      }
    } catch (_error) {

    }
  });

}).call(this);

(function() {
  var depressFindBattle, depressFindBattleUnranked;

  $(function() {
    var $mainButtons, challengeobj, challengeobjunranked, challengepaneobj, challengepaneobjunranked;
    $mainButtons = $('.main_buttons');
    $mainButtons.on('click', '.teambuilder_button', function(e) {
      return PokeBattle.navigation.showTeambuilder();
    });
    challengeobjunranked = {
      eventName: "findBattleunranked",
      populate: $mainButtons.find('.find_battle_select_team'),
      button: $mainButtons.find('.find_battle_non_ranked'),
      defaultClauses: [Conditions.SLEEP_CLAUSE, Conditions.EVASION_CLAUSE, Conditions.SPECIES_CLAUSE, Conditions.OHKO_CLAUSE, Conditions.PRANKSTER_SWAGGER_CLAUSE, Conditions.UNRELEASED_BAN, Conditions.TIMED_BATTLE],
      blockedClauses: true
    };
    challengeobj = {
      eventName: "findBattle",
      populate: $mainButtons.find('.find_battle_select_team'),
      button: $mainButtons.find('.find_battle'),
      defaultClauses: [Conditions.SLEEP_CLAUSE, Conditions.EVASION_CLAUSE, Conditions.SPECIES_CLAUSE, Conditions.OHKO_CLAUSE, Conditions.PRANKSTER_SWAGGER_CLAUSE, Conditions.UNRELEASED_BAN, Conditions.RATED_BATTLE, Conditions.TIMED_BATTLE],
      blockedClauses: true
    };
    challengepaneobjunranked = new challengePaneObject(challengeobjunranked);
    challengePaneArray.push(challengepaneobjunranked);
    challengepaneobj = new challengePaneObject(challengeobj);
    challengePaneArray.push(challengepaneobj);
    createChallengePane({
      eventName: "findBattleunranked",
      populate: $mainButtons.find('.find_battle_select_team'),
      button: $mainButtons.find('.find_battle_non_ranked'),
      defaultClauses: [Conditions.SLEEP_CLAUSE, Conditions.EVASION_CLAUSE, Conditions.SPECIES_CLAUSE, Conditions.OHKO_CLAUSE, Conditions.PRANKSTER_SWAGGER_CLAUSE, Conditions.UNRELEASED_BAN, Conditions.TIMED_BATTLE],
      blockedClauses: true
    });
    createChallengePane({
      eventName: "findBattle",
      populate: $mainButtons.find('.find_battle_select_team'),
      button: $mainButtons.find('.find_battle'),
      defaultClauses: [Conditions.SLEEP_CLAUSE, Conditions.EVASION_CLAUSE, Conditions.SPECIES_CLAUSE, Conditions.OHKO_CLAUSE, Conditions.PRANKSTER_SWAGGER_CLAUSE, Conditions.UNRELEASED_BAN, Conditions.RATED_BATTLE, Conditions.TIMED_BATTLE],
      blockedClauses: true
    });
    $mainButtons.find('.find_battle').on('challenge', function() {
      var $this;
      $this = $(this);
      return $this.find('.find-icon').addClass('icon-spinner spinner-anim').removeClass("icon-earth");
    });
    $mainButtons.find('.find_battle_non_ranked').on('challenge', function() {
      var $this;
      $this = $(this);
      return $this.find('.find-icon').addClass('icon-spinner spinner-anim').removeClass("icon-earth");
    });
    return $mainButtons.find('.display_credits').click(function() {
      var $modal;
      $modal = PokeBattle.modal('modals/credits');
      return $modal.find('.modal-footer button').first().focus();
    });
  });

  depressFindBattle = function() {
    var $button, $mainButtons;
    $mainButtons = $('.main_buttons');
    $button = $mainButtons.find('.find_battle');
    $button.removeClass("disabled");
    $button.find('.find-icon').removeClass("icon-spinner spinner-anim").addClass("icon-earth");
    return $mainButtons.find('.find_battle_select_team .select').removeClass('disabled');
  };

  depressFindBattleUnranked = function() {
    var $button, $mainButtons;
    $mainButtons = $('.main_buttons');
    $button = $mainButtons.find('.find_battle_non_ranked');
    $button.removeClass("disabled");
    $button.find('.find-icon').removeClass("icon-spinner spinner-anim").addClass("icon-earth");
    return $mainButtons.find('.find_battle_select_team .select').removeClass('disabled');
  };

  $(window).load(function() {
    var $mainButtons;
    $mainButtons = $('.main_buttons');
    PokeBattle.battles.on('add', function(battle) {
      if (!battle.get('spectating')) {
        depressFindBattle();
        return depressFindBattleUnranked();
      }
    });
    PokeBattle.primus.on('findBattleCanceled', depressFindBattle);
    PokeBattle.events.on('findBattleCanceled', depressFindBattle);
    PokeBattle.primus.on('findBattleCanceledUnranked', depressFindBattleUnranked);
    return PokeBattle.events.on('findBattleCanceledUnranked', depressFindBattleUnranked);
  });

}).call(this);

(function() {
  $(document).on('click', '.open_pm', function() {
    var $this, message;
    $this = $(this);
    message = PokeBattle.messages.add({
      id: $this.data('user-id')
    });
    message.trigger('open', message);
    return message.trigger('focus', message);
  });

  PokeBattle.primus.on('privateMessage', function(messageId, fromUserId, messageText) {
    var message;
    message = PokeBattle.messages.add({
      id: messageId
    });
    return message.add(fromUserId, messageText);
  });

  PokeBattle.primus.on('challenge', function(fromUserId, generation, conditions) {
    var message;
    message = PokeBattle.messages.add({
      id: fromUserId
    });
    message.add(fromUserId, "You have been challenged!", {
      type: "alert"
    });
    return message.openChallenge(fromUserId, generation, conditions);
  });

  PokeBattle.primus.on('cancelChallenge', function(fromUserId) {
    var message;
    message = PokeBattle.messages.add({
      id: fromUserId
    });
    message.add(fromUserId, "The challenge was canceled!", {
      type: "alert"
    });
    return message.closeChallenge(fromUserId);
  });

  PokeBattle.primus.on('rejectChallenge', function(fromUserId) {
    var message;
    message = PokeBattle.messages.add({
      id: fromUserId
    });
    message.add(fromUserId, "The challenge was rejected!", {
      type: "alert"
    });
    return message.closeChallenge(fromUserId);
  });

  PokeBattle.primus.on('challengeSuccess', function(fromUserId) {
    var message;
    message = PokeBattle.messages.add({
      id: fromUserId
    });
    return message.closeChallenge(fromUserId);
  });

}).call(this);

(function() {
  var PokeBattleRouter,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  PokeBattleRouter = (function(_super) {
    __extends(PokeBattleRouter, _super);

    function PokeBattleRouter() {
      this.spectateBattle = __bind(this.spectateBattle, this);
      this.main = __bind(this.main, this);
      return PokeBattleRouter.__super__.constructor.apply(this, arguments);
    }

    PokeBattleRouter.prototype.routes = {
      "": "main",
      "battles/:id": "spectateBattle"
    };

    PokeBattleRouter.prototype.main = function() {
      var $navigation;
      $navigation = $('#navigation');
      return $navigation.find('.nav_item').first().click();
    };

    PokeBattleRouter.prototype.spectateBattle = function(id) {
      if (PokeBattle.battles.get(id)) {
        return PokeBattle.navigation.changeWindowToBattle(id);
      } else {
        return PokeBattle.primus.send('spectateBattle', id);
      }
    };

    return PokeBattleRouter;

  })(Backbone.Router);

  PokeBattle.router = new PokeBattleRouter();

  PokeBattle.primus.once("loginSuccess", function() {
    var routed;
    if (Backbone.History.started) {
      return;
    }
    PokeBattle.events.trigger("ready");
    return routed = Backbone.history.start({
      pushState: true
    });
  });

}).call(this);

(function() {
  $(document).on('click', '.spectate', function() {
    var battleId;
    battleId = $(this).data('battle-id');
    PokeBattle.router.navigate("battles/" + battleId, {
      trigger: true
    });
    return false;
  });

}).call(this);

(function() {
  PokeBattle.primus.on('version', function(version) {
    var $modal;
    if (version !== PokeBattle.CLIENT_VERSION) {
      $modal = PokeBattle.modal('modals/new_client', function($modal) {
        return $modal.on('click', '.button_refresh', function() {
          return window.location.reload(true);
        });
      });
      return $modal.find('button').first().focus();
    }
  });

}).call(this);

(function() {
  var DEFAULT_INTERVAL, notifications, original, timeoutId;

  DEFAULT_INTERVAL = 1000;

  original = document.title;

  timeoutId = void 0;

  $.flashTitle = function(newMsg, interval) {
    if (newMsg === false) {
      clearTimeout(timeoutId);
      return document.title = original;
    } else {
      interval = interval || DEFAULT_INTERVAL;
      return timeoutId = setTimeout(function() {
        clearTimeout(timeoutId);
        document.title = document.title === original ? newMsg : original;
        return timeoutId = setTimeout(arguments.callee, interval);
      }, interval);
    }
  };

  PokeBattle.NotificationTypes = {
    PRIVATE_MESSAGE: {
      showDesktop: false
    },
    BATTLE_STARTED: {
      showDesktop: true,
      prefix: "bs",
      title: "Battle Started",
      body: "Your battle has started!"
    },
    ACTION_REQUESTED: {
      showDesktop: true,
      prefix: "ar",
      title: "Battle Action Requested",
      body: "A battle is ready for your input!"
    }
  };

  notifications = [];

  PokeBattle.requestNotifyPermission = (function(_this) {
    return function() {
      if (notify.permissionLevel() === notify.PERMISSION_DEFAULT) {
        return notify.requestPermission();
      }
    };
  })(this);

  PokeBattle.notifyUser = (function(_this) {
    return function(type, identifier) {
      var notification;
      if (document.hasFocus()) {
        return;
      }
      $.flashTitle("You have new notification(s)");
      if (type.showDesktop) {
        notification = notify.createNotification(type.title, {
          icon: "//media.pokebattle.com/logo/pb_red.png",
          body: type.body,
          tag: "PokeBattle_" + type.prefix + "_" + identifier
        });
        return notifications.push(notification);
      }
    };
  })(this);

  $(window).focus(function() {
    var notification, _i, _len;
    $.flashTitle(false);
    for (_i = 0, _len = notifications.length; _i < _len; _i++) {
      notification = notifications[_i];
      notification.close();
    }
    return notifications = [];
  });

}).call(this);

(function() {
  var TeamStore,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  TeamStore = (function(_super) {
    __extends(TeamStore, _super);

    function TeamStore() {
      this.saveRemotely = __bind(this.saveRemotely, this);
      this.loadLocally = __bind(this.loadLocally, this);
      this.saveLocally = __bind(this.saveLocally, this);
      this.unsavedTeams = __bind(this.unsavedTeams, this);
      return TeamStore.__super__.constructor.apply(this, arguments);
    }

    TeamStore.prototype.model = Team;

    TeamStore.prototype.initialize = function() {
      this.on('add remove reset remoteSync', this.saveLocally);
      return this.loadLocally();
    };

    TeamStore.prototype.unsavedTeams = function() {
      return this.filter(function(team) {
        return !team.id || team.get('saving');
      });
    };

    TeamStore.prototype.saveLocally = function() {
      var json, teams;
      teams = this.unsavedTeams();
      json = _.map(teams, function(team) {
        return team.toJSON();
      });
      try {
        return window.localStorage.setItem('local_teams', JSON.stringify(json));
      } catch (_error) {
        return console.error("Failed to save teams locally.");
      }
    };

    TeamStore.prototype.loadLocally = function() {
      var json, teams;
      try {
        json = window.localStorage.getItem('local_teams');
        if (!json) {
          return;
        }
        teams = JSON.parse(json);
        if (teams.length > 0) {
          return this.add(teams);
        }
      } catch (_error) {
        return console.error("Failed to load teams locally.");
      }
    };

    TeamStore.prototype.saveRemotely = function() {
      var team, teams, _i, _len, _results;
      teams = this.unsavedTeams();
      _results = [];
      for (_i = 0, _len = teams.length; _i < _len; _i++) {
        team = teams[_i];
        _results.push(team.save());
      }
      return _results;
    };

    return TeamStore;

  })(Backbone.Collection);

  PokeBattle.TeamStore = new TeamStore();

  PokeBattle.primus.on('receiveTeams', function(remoteTeams) {
    var $modal, domId, ids, localJSON, localTeam, remoteJSON, remoteTeam, teamText, unsavedTeam, _i, _len, _ref;
    remoteTeams = remoteTeams.map(function(team) {
      team.teambuilder = true;
      return new Team(team);
    });
    ids = PokeBattle.TeamStore.pluck('id');
    for (_i = 0, _len = remoteTeams.length; _i < _len; _i++) {
      remoteTeam = remoteTeams[_i];
      if (!(_ref = remoteTeam.id, __indexOf.call(ids, _ref) >= 0)) {
        continue;
      }
      remoteJSON = remoteTeam.toJSON();
      localTeam = PokeBattle.TeamStore.get(remoteTeam.id);
      unsavedTeam = localTeam.clone();
      unsavedTeam.set(localTeam.previousAttributes(), {
        silent: true
      });
      localJSON = unsavedTeam.toJSON();
      if (!_.isEqual(remoteJSON, localJSON)) {
        teamText = PokeBattle.exportTeam(remoteJSON.pokemon);
        domId = "teams-differ-" + remoteTeam.id;
        $modal = PokeBattle.modal('modals/teams_differ', domId, {
          teamText: teamText
        });
        $modal.find('textarea').first().focus();
        (function(localTeam, remoteJSON) {
          return $modal.find('.button_override').one('click', function() {
            localTeam.set(remoteJSON, {
              silent: true
            });
            localTeam.trigger('render', localTeam);
            return $modal.modal('hide');
          });
        })(localTeam, remoteJSON);
      }
    }
    return PokeBattle.TeamStore.add(remoteTeams);
  });

  PokeBattle.primus.on('loginSuccess', function() {
    return PokeBattle.primus.send('requestTeams');
  });

}).call(this);

(function() {
  $(function() {
    var $navigation;
    $navigation = $("#navigation");
    $(".show-navigation").click((function(_this) {
      return function() {
        var active;
        active = $navigation.hasClass('active');
        return $navigation.toggleClass('active', !active);
      };
    })(this));
    return $navigation.on('click', '.nav_item', function() {
      return $navigation.removeClass("active");
    });
  });

}).call(this);
